Anidamiento complejo de parciales y plantillas.

Resuelto PhillipKregg asked hace 12 años • 6 respuestas

Mi pregunta es cómo lidiar con el anidamiento complejo de plantillas (también llamados parciales ) en una aplicación AngularJS.

La mejor manera de describir mi situación es con una imagen que creé:

Diagrama de página AngularJS

Como puede ver, tiene el potencial de ser una aplicación bastante compleja con muchos modelos anidados.

La aplicación es de una sola página, por lo que carga un index.html que contiene un elemento div en el DOM con el ng-viewatributo.

Para el círculo 1 , verá que hay una navegación principal que carga las plantillas apropiadas en el archivo ng-view. Hago esto pasando $routeParamsal módulo principal de la aplicación. Aquí hay un ejemplo de lo que hay en mi aplicación:

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' })       

    }]);

En el círculo 2 , la plantilla que se carga en el tiene una subnavegaciónng-view adicional . Este subnav luego necesita cargar plantillas en el área debajo de él, pero como ya se está usando ng-view, no estoy seguro de cómo hacerlo.

Sé que puedo incluir plantillas adicionales dentro de la primera plantilla, pero todas estas plantillas serán bastante complejas. Me gustaría mantener todas las plantillas separadas para que la aplicación sea más fácil de actualizar y no depender de que la plantilla principal deba cargarse para poder acceder a sus elementos secundarios.

En el círculo 3 , puedes ver que las cosas se vuelven aún más complejas. Existe la posibilidad de que las plantillas de subnavegación tengan una segunda subnavegación que también necesitará cargar sus propias plantillas en el área del círculo 4.

¿Cómo se puede estructurar una aplicación AngularJS para lidiar con un anidamiento de plantillas tan complejo y al mismo tiempo mantenerlas separadas unas de otras?

PhillipKregg avatar Oct 12 '12 23:10 PhillipKregg
Aceptado

ACTUALIZACIÓN: consulte el nuevo proyecto de AngularUI para abordar este problema


Para las subsecciones es tan fácil como aprovechar cadenas en ng-include:

<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>

O puede crear un objeto en caso de que tenga enlaces a subpáginas por todas partes:

$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>

O incluso puedes usar$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>

También puedes poner un controlador ng en el nivel más alto de cada parcial.

ProLoser avatar Oct 15 '2012 21:10 ProLoser

Bueno, dado que actualmente solo puedes tener una directiva ngView... uso controles de directiva anidados. Esto le permite configurar plantillas y heredar (o aislar) ámbitos entre ellas. Aparte de eso, uso ng-switch o incluso simplemente ng-show para elegir qué controles estoy mostrando en función de lo que viene de $routeParams.

EDITAR Aquí hay un pseudocódigo de ejemplo para darle una idea de lo que estoy hablando. Con una subnavegación anidada.

Aquí está la página principal de la aplicación.

<!-- 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>

Directiva para la subnavegación

app.directive('mySubNav', function(){
    return {
        restrict: 'E',
        scope: {
           current: '=current'
        },
        templateUrl: 'mySubNav.html',
        controller: function($scope) {
        }
    };
});

plantilla para la subnavegación

<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>

plantilla para una página principal (desde la navegación principal)

<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>

Controlador para una página principal. (desde el navegador principal)

app.controller('page1Ctrl', function($scope, $routeParams) {
     $scope.sub = $routeParams.sub;
});

Directiva para una subárea

app.directive('mySubArea1', function(){
    return {
        restrict: 'E',
        templateUrl: 'mySubArea1.html',
        controller: function($scope) {
            //controller for your sub area.
        }
    };
});
Ben Lesh avatar Oct 12 '2012 17:10 Ben Lesh

También puede retirar esta biblioteca con el mismo propósito:

http://segmento-de-ruta-angular.com

Parece lo que estás buscando y es mucho más sencillo de usar que ui-router. Desde el sitio de demostración :

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 nivel superior:

<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>

HTML anidado:

<h4>Section 1</h4>
Section 1 contents.
<div app-view-segment="1"></div>
artch avatar Aug 15 '2013 10:08 artch

Yo también estaba luchando con las vistas anidadas en Angular.

Una vez que conseguí ui-router , supe que nunca volvería a la funcionalidad de enrutamiento predeterminada de Angular.

A continuación se muestra una aplicación de ejemplo que utiliza múltiples niveles de anidamiento de vistas.

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',
    });
});

Como puede verse, hay 4 vistas principales (vista1, vista2, vista3, vista4) y la vista1 tiene 3 vistas secundarias.

Dan Ochiana avatar Sep 03 '2014 11:09 Dan Ochiana