Imbrication complexe de partiels et de gabarits
ma question porte sur la façon de traiter l'imbrication complexe de templates (aussi appelé partials ) dans une application AngularJS.
la meilleure façon de décrire ma situation est avec une image que j'ai créée:
comme vous pouvez le voir cela a le potentiel d'être une application assez complexe avec beaucoup de modèles imbriqués.
L'application est une page, donc elle charge un index .html qui contient un élément div dans le DOM avec l'attribut ng-view
.
pour le cercle 1 , vous voyez qu'il y a une navigation primaire qui charge les gabarits appropriés dans le ng-view
. Je le fais en passant $routeParams
au module principal de l'application. Voici un exemple de ce qui est dans mon application:
angular.module('myApp', []).
config(['$routeProvider', function($routeProvider) {
$routeProvider.
when("/job/:jobId/zones/:zoneId", { controller: JobDetailController, templateUrl: 'assets/job_list_app/templates/zone_edit.html' }).
when("/job/:jobId/initial_inspection", { controller: JobDetailController, templateUrl: 'assets/job_list_app/templates/initial_inspection.html' }).
when("/job/:jobId/zones/:zoneId/rooms/:roomId", { controller: JobDetailController, templateUrl: 'assets/job_list_app/templates/room_edit.html' })
}]);
dans le cercle 2 , le gabarit qui est chargé dans le ng-view
a un Sous-navigation supplémentaire . Ce sous-nav a ensuite besoin de charger des modèles dans la zone ci - dessous-mais comme la vue ng est déjà utilisée, Je ne suis pas sûr de savoir comment faire cela.
je sais que je peux inclure des gabarits supplémentaires dans le 1er gabarit, mais ces gabarits vont tous être assez complexe. Je voudrais garder tous les modèles séparer afin de rendre l'application plus facile à mettre à jour et de ne pas avoir une dépendance sur le modèle parent doit être chargé afin d'accéder à ses enfants.
dans le cercle 3 , vous pouvez voir les choses devenir encore plus complexe. Il est possible que les modèles de sous-navigation aient un deuxième sous-navigation qui devra charger ses propres modèles ainsi dans la zone dans cercle 4
comment structurer une application AngularJS pour faire face à un tel enchevêtrement complexe de gabarits tout en les gardant tous séparés les uns des autres?
6 réponses
bien, puisque vous ne pouvez avoir actuellement qu'une seule directive ngView... J'utilise des commandes de directive imbriquées. Cela vous permet de configurer des échelles de templage et d'hériter (ou d'isoler) d'entre elles. En dehors de cela, j'utilise ng-switch ou même juste ng-show pour choisir les contrôles que j'affiche en fonction de ce qui vient de $routeParams.
EDIT voici un exemple de pseudo-code pour vous donner une idée de ce dont je parle. Avec une navigation de sous-marin imbriquée.
Voici l'application principale
<!-- primary nav -->
<a href="#/page/1">Page 1</a>
<a href="#/page/2">Page 2</a>
<a href="#/page/3">Page 3</a>
<!-- display the view -->
<div ng-view>
</div>
Directive pour la sous-navigation
app.directive('mySubNav', function(){
return {
restrict: 'E',
scope: {
current: '=current'
},
templateUrl: 'mySubNav.html',
controller: function($scope) {
}
};
});
modèle pour la sous-navigation
<a href="#/page/1/sub/1">Sub Item 1</a>
<a href="#/page/1/sub/2">Sub Item 2</a>
<a href="#/page/1/sub/3">Sub Item 3</a>
modèle de page principale (de la navigation principale)
<my-sub-nav current="sub"></my-sub-nav>
<ng-switch on="sub">
<div ng-switch-when="1">
<my-sub-area1></my-sub-area>
</div>
<div ng-switch-when="2">
<my-sub-area2></my-sub-area>
</div>
<div ng-switch-when="3">
<my-sub-area3></my-sub-area>
</div>
</ng-switch>
contrôleur pour une page principale. (de la navigation primaire)
app.controller('page1Ctrl', function($scope, $routeParams) {
$scope.sub = $routeParams.sub;
});
Directive pour une sous-zone
app.directive('mySubArea1', function(){
return {
restrict: 'E',
templateUrl: 'mySubArea1.html',
controller: function($scope) {
//controller for your sub area.
}
};
});
mise à jour: consultez le nouveau projet D'AngularUI pour résoudre ce problème
pour les sous-sections c'est aussi simple que de tirer des chaînes en ng-incluez:
<ul id="subNav">
<li><a ng-click="subPage='section1/subpage1.htm'">Sub Page 1</a></li>
<li><a ng-click="subPage='section1/subpage2.htm'">Sub Page 2</a></li>
<li><a ng-click="subPage='section1/subpage3.htm'">Sub Page 3</a></li>
</ul>
<ng-include src="subPage"></ng-include>
ou vous pouvez créer un objet si vous avez des liens vers des sous-pages partout:
$scope.pages = { page1: 'section1/subpage1.htm', ... };
<ul id="subNav">
<li><a ng-click="subPage='page1'">Sub Page 1</a></li>
<li><a ng-click="subPage='page2'">Sub Page 2</a></li>
<li><a ng-click="subPage='page3'">Sub Page 3</a></li>
</ul>
<ng-include src="pages[subPage]"></ng-include>
ou vous pouvez même utiliser $routeParams
$routeProvider.when('/home', ...);
$routeProvider.when('/home/:tab', ...);
$scope.params = $routeParams;
<ul id="subNav">
<li><a href="#/home/tab1">Sub Page 1</a></li>
<li><a href="#/home/tab2">Sub Page 2</a></li>
<li><a href="#/home/tab3">Sub Page 3</a></li>
</ul>
<ng-include src=" '/home/' + tab + '.html' "></ng-include>
vous pouvez également mettre un contrôleur ng au niveau le plus élevé de chaque partielle
vous pouvez également consulter cette bibliothèque pour le même usage:
http://angular-route-segment.com
Il ressemble à ce que vous recherchez, et c'est beaucoup plus simple à utiliser que l'interface utilisateur du routeur. Du Démo site :
JS:
$routeSegmentProvider.
when('/section1', 's1.home').
when('/section1/:id', 's1.itemInfo.overview').
when('/section2', 's2').
segment('s1', {
templateUrl: 'templates/section1.html',
controller: MainCtrl}).
within().
segment('home', {
templateUrl: 'templates/section1/home.html'}).
segment('itemInfo', {
templateUrl: 'templates/section1/item.html',
controller: Section1ItemCtrl,
dependencies: ['id']}).
within().
segment('overview', {
templateUrl: 'templates/section1/item/overview.html'}).
HTML de haut niveau:
<ul>
<li ng-class="{active: $routeSegment.startsWith('s1')}">
<a href="/section1">Section 1</a>
</li>
<li ng-class="{active: $routeSegment.startsWith('s2')}">
<a href="/section2">Section 2</a>
</li>
</ul>
<div id="contents" app-view-segment="0"></div>
imbriqué HTML:
<h4>Section 1</h4>
Section 1 contents.
<div app-view-segment="1"></div>
moi aussi je me débattais avec des vues emboîtées dans L'angle.
une fois que j'ai obtenu une prise de ui-routeur je savais que je ne retournerais jamais à la fonctionnalité de routage angulaire par défaut.
voici un exemple d'application qui utilise plusieurs niveaux de vues imbrication""
app.config(function ($stateProvider, $urlRouterProvider,$httpProvider) {
// navigate to view1 view by default
$urlRouterProvider.otherwise("/view1");
$stateProvider
.state('view1', {
url: '/view1',
templateUrl: 'partials/view1.html',
controller: 'view1.MainController'
})
.state('view1.nestedViews', {
url: '/view1',
views: {
'childView1': { templateUrl: 'partials/view1.childView1.html' , controller: 'childView1Ctrl'},
'childView2': { templateUrl: 'partials/view1.childView2.html', controller: 'childView2Ctrl' },
'childView3': { templateUrl: 'partials/view1.childView3.html', controller: 'childView3Ctrl' }
}
})
.state('view2', {
url: '/view2',
})
.state('view3', {
url: '/view3',
})
.state('view4', {
url: '/view4',
});
});
comme on peut le voir,il y a 4 vues principales (vue 1,vue 2,vue 3, vue 4) et la vue 1 A 3 vues d'enfant.
vous pouvez utiliser ng-include pour éviter d'utiliser ng-views imbriquées.
http://docs.angularjs.org/api/ng/directive/ngInclude
http://plnkr.co/edit/ngdoc:example-example39@snapshot?p=preview
ma page d'index j'utilise ng-view. Puis sur mes sous-pages dont j'ai besoin d'avoir des cadres imbriqués. J'utilise ng-include. La démo montre une liste déroulante. J'ai remplacé le mien par un lien ng-click. Dans le fonction je mettrais $champ d'application.modèle = $champ d'application.modèles[0]; ou $scope.modèle = $champ d'application.templates[1];
$scope.clickToSomePage= function(){
$scope.template = $scope.templates[0];
};
Routeur angulaire ui-supporte les vues emboîtées. Je n'ai pas encore utilisé mais semble très prometteur.