部分和模板的复杂嵌套

Phi*_*egg 501 javascript angularjs

我的问题涉及如何在AngularJS应用程序中处理模板(也称为部分)的复杂嵌套.

描述我的情况的最好方法是使用我创建的图像:

AngularJS页面图

正如您所看到的,这可能是一个包含大量嵌套模型的相当复杂的应用程序.

应用程序是单页面的,因此它会加载一个index.html,其中包含DOM中带有ng-view属性的div元素.

对于圆圈1,您会看到有一个主要导航将相应的模板加载到ng-view.我是通过传递$routeParams到主app模块来做到这一点的.这是我的应用程序中的一个示例:

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

    }]);
Run Code Online (Sandbox Code Playgroud)

在圆圈2中,加载到其中的模板ng-view具有附加的子导航.然后这个子导航需要将模板加载到它下面的区域 - 但由于ng-view已被使用,我不知道如何去做.

我知道我可以在第一个模板中包含其他模板,但这些模板都非常复杂.我想将所有模板分开,以使应用程序更容易更新,并且不必依赖于必须加载的父模板才能访问其子代.

在第3圈中,您可以看到事情变得更加复杂.子导航模板可能具有第二个子导航,需要将其自己的模板加载到圆圈4中的区域

如何构建AngularJS应用程序来处理模板的这种复杂嵌套,同时保持它们彼此分离?

Pro*_*ser 197

更新: 查看AngularUI的新项目以解决此问题


对于小节,它就像在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>
Run Code Online (Sandbox Code Playgroud)

或者,您可以创建一个对象,以防您在整个地方都有子页面的链接:

$scope.pages = { page1: 'section1/subpage1.htm', ... };
Run Code Online (Sandbox Code Playgroud)
<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>
Run Code Online (Sandbox Code Playgroud)

或者你甚至可以使用 $routeParams

$routeProvider.when('/home', ...);
$routeProvider.when('/home/:tab', ...);
$scope.params = $routeParams;
Run Code Online (Sandbox Code Playgroud)
<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>
Run Code Online (Sandbox Code Playgroud)

您还可以将ng控制器放在每个部分的最顶层

  • 我更喜欢你的解决方案.我是Angular的新手,从我看到网络到现在为止,这似乎更容易理解.谁知道,可能是blesh使用更多的角度框架来做它,但似乎你用更少的代码行以更合理的方式钉它.谢谢! (8认同)
  • 我有与OP相同的设计问题.有没有人尝试过AngularUI状态机制?我非常不愿意使用另一个第三方库,我宁愿坚持使用AngularJS的"做事方式".但另一方面,路由系统似乎是它的致命弱点... @PhillipKregg,你最终用什么来解决这个问题呢? (4认同)
  • 您可以指定`<div ng-include ="'/ home /'+ tab +'.html'"ng-controller ="SubCtrl"> </ div>`,以便为子项使用单独的控制器/范围模板.或者只是在子模板中的任何位置指定`ngController`指令,为每个部分使用不同的控制器. (4认同)
  • @ProLooser也许你的意思是这个链接https://github.com/angular-ui/ui-router ...你粘贴的那个是破的 (2认同)
  • @DerekAdair项目相当稳定(尽管版本号)并且在一些地方用于生产.它可以防止不必要的控制器重新加载,是我建议的解决方案的更好的替代方案. (2认同)

Ben*_*esh 171

好吧,因为你现在只能有一个ngView指令...我使用嵌套的指令控件.这允许您在它们之间设置模板和继承(或隔离)范围.除此之外,我使用ng-switch甚至只是ng-show来根据$ routeParams中的内容选择我正在显示的控件.

编辑这里有一些示例伪代码,可以让您了解我在说什么.使用嵌套的子导航.

这是主应用页面

<!-- 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>
Run Code Online (Sandbox Code Playgroud)

子导航指令

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

子导航的模板

<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>
Run Code Online (Sandbox Code Playgroud)

主页面的模板(来自主导航)

<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>
Run Code Online (Sandbox Code Playgroud)

主页的控制器.(来自主导航)

app.controller('page1Ctrl', function($scope, $routeParams) {
     $scope.sub = $routeParams.sub;
});
Run Code Online (Sandbox Code Playgroud)

子区域的指令

app.directive('mySubArea1', function(){
    return {
        restrict: 'E',
        templateUrl: 'mySubArea1.html',
        controller: function($scope) {
            //controller for your sub area.
        }
    };
});
Run Code Online (Sandbox Code Playgroud)

  • 我更喜欢ProLoser的解决方案,我们在我们的应用程序上做了类似的事情并且它运行良好.blesh解决方案的问题是控制器代码进入指令.通常,您在指令中指定的控制器是与ex:ngModelCtrl的指令紧密配合的控制器,它与输入和其他指令紧密配合.在你的情况下,将控制器代码放在一个指令中将是代码气味,它实际上是一个独立的控制器. (9认同)
  • 我认为这个解决方案应该是"嵌套视图不起作用"的任何问题的第一个答案.只是因为它更接近Angular意识形态而不是使用ui-router等等.谢谢. (8认同)

art*_*tch 26

您也可以出于同样目的签出此库:

http://angular-route-segment.com

它看起来像你在寻找,它比ui-router更简单.从演示网站:

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'}).
Run Code Online (Sandbox Code Playgroud)

顶级HTML:

<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>
Run Code Online (Sandbox Code Playgroud)

嵌套HTML:

<h4>Section 1</h4>
Section 1 contents.
<div app-view-segment="1"></div>
Run Code Online (Sandbox Code Playgroud)


Dan*_*ana 17

我也在使用Angular中的嵌套视图.

一旦我掌握了ui-router,我就知道我永远不会回到角度默认路由功能.

这是一个使用多级视图嵌套的示例应用程序

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',
    });
});
Run Code Online (Sandbox Code Playgroud)

可以看出有4个主视图(view1,view2,view3,view4),view1有3个子视图.

  • 注入`$ httpProvider`的目的是什么?我没有看到它在任何地方使用过. (2认同)