Tổ hợp phức tạp của các hạt và mẫu


503

Câu hỏi của tôi liên quan đến cách xử lý các mẫu lồng nhau phức tạp (còn gọi là partials ) trong ứng dụng AngularJS.

Cách tốt nhất để mô tả tình huống của tôi là với một hình ảnh tôi đã tạo:

Sơ đồ trang AngularJS

Như bạn có thể thấy điều này có tiềm năng trở thành một ứng dụng khá phức tạp với rất nhiều mô hình lồng nhau.

Ứng dụng này là một trang, do đó, nó tải một index.html có chứa phần tử div trong DOM với ng-viewthuộc tính.

Đối với vòng tròn 1 , Bạn thấy rằng có một Điều hướng chính tải các mẫu thích hợp vào ng-view. Tôi đang làm điều này bằng cách chuyển $routeParamsđến mô-đun ứng dụng chính. Đây là một ví dụ về những gì trong ứng dụng của tôi:

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

    }]);

Trong vòng tròn 2 , mẫu được tải vào ng-viewcó thêm một điều hướng phụ . Điều hướng phụ này sau đó cần tải các mẫu vào khu vực bên dưới nó - nhưng vì ng-view đã được sử dụng, tôi không chắc chắn cách thực hiện việc này.

Tôi biết rằng tôi có thể bao gồm các mẫu bổ sung trong mẫu thứ 1, nhưng tất cả các mẫu này sẽ khá phức tạp. Tôi muốn giữ tất cả các mẫu riêng biệt để làm cho ứng dụng dễ cập nhật hơn và không bị phụ thuộc vào mẫu cha mẹ phải được tải để truy cập vào con của nó.

Trong vòng tròn 3 , bạn có thể thấy mọi thứ thậm chí còn phức tạp hơn. Có khả năng các mẫu điều hướng phụ sẽ có điều hướng phụ thứ 2 sẽ cần tải các mẫu của chính nó vào khu vực trong vòng tròn 4

Làm thế nào một người đi về cấu trúc một ứng dụng AngularJS để đối phó với các mẫu lồng nhau phức tạp như vậy trong khi giữ tất cả chúng tách biệt với nhau?


3
Nếu bạn vẫn theo dõi chủ đề này, tôi đã thêm một liên kết đến dự án AngularUI mới để giải quyết vấn đề này và bản demo thứ ba được cung cấp bởi các chương trình con mà không cần chỉ thị cho câu trả lời của tôi.
ProLoser

2
cái này thì sao? bennadel.com/blog/ từ
ericbae

82
Câu hỏi hay nhất tôi từng thấy trong một thời gian dài :)
Mark Nadig

2
đã đồng ý! Yêu thích việc sử dụng mockup
Bryan Hong

4
Sẽ là tuyệt vời để thêm liên kết đến các lựa chọn thay thế trực tiếp trong câu hỏi ở đây. github.com/angular-ui/ui-router github.com/artch/angular-route-sibution github.com/dotJEM/angular-routing
Jens

Câu trả lời:


171

Chà, vì hiện tại bạn chỉ có thể có một lệnh ngView ... Tôi sử dụng các điều khiển chỉ thị lồng nhau. Điều này cho phép bạn thiết lập phạm vi tạo khuôn mẫu và kế thừa (hoặc cô lập) giữa chúng. Ngoài ra, tôi sử dụng ng-switch hoặc thậm chí chỉ ng-show để chọn điều khiển nào tôi đang hiển thị dựa trên những gì đến từ $ routeParams.

EDIT Đây là một số ví dụ mã giả để cho bạn biết về những gì tôi đang nói. Với một điều hướng phụ lồng nhau.

Đây là trang ứng dụng chính

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

Chỉ thị cho điều hướng phụ

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

mẫu cho điều hướng phụ

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

mẫu cho một trang chính (từ điều hướng chính)

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

Bộ điều khiển cho một trang chính. (từ hải quân chính)

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

Chỉ thị cho một khu vực phụ

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

9
Tôi thích giải pháp của ProLuler hơn, chúng tôi làm điều gì đó tương tự trên ứng dụng của mình và nó đã hoạt động tốt. Vấn đề với giải pháp của b Meat là mã điều khiển đi vào các chỉ thị. Thông thường bộ điều khiển mà bạn chỉ định trong một lệnh là một bộ điều khiển hoạt động chặt chẽ với lệnh cho ex: ngModelCtrl hoạt động chặt chẽ với đầu vào và các lệnh khác. Trong trường hợp của bạn, việc đặt mã điều khiển trong một lệnh sẽ là mùi mã, nó thực sự là một bộ điều khiển độc lập.
ChrisOdney

@bleh, tốt đẹp! Nó có vẻ thực sự giải thích tốt nhưng với tư cách là một lập trình viên giỏi và người mới bắt đầu trong AngularJS, tôi không nắm bắt được điều đó ... Tôi và cộng đồng sẽ thực sự thích một liên kết JSFiddle với một mẫu đang hoạt động bằng cách sử dụng phương pháp đó. Diggin nó xung quanh sẽ là dễ hiểu! :) Cảm ơn
Roger Barreto

8
Tôi nghĩ giải pháp này nên là câu trả lời đầu tiên cho bất kỳ câu hỏi nào về 'chế độ xem lồng nhau không hoạt động'. Chỉ vì nó gần với hệ tư tưởng Angular hơn là sử dụng bộ định tuyến ui và vv. Cảm ơn.
Sergei Panfilov

Vậy câu trả lời là chỉ thị?
Marc M.

để làm nổi bật các mục điều hướng phụ bạn có thể sử dụng: coder1.com/articles/angularjs-managing-active-nav-elements đây có phải là cách tốt để làm điều đó không?
thoát mèo

198

CẬP NHẬT: Kiểm tra dự án mới của AngularUI để giải quyết vấn đề này


Đối với các phần phụ, nó dễ dàng như tận dụng các chuỗi trong ng-bao gồm:

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

Hoặc bạn có thể tạo một đối tượng trong trường hợp bạn có liên kết đến các trang phụ ở khắp mọi nơi:

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

Hoặc thậm chí bạn có thể sử dụng $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>

Bạn cũng có thể đặt bộ điều khiển ng ở cấp cao nhất của từng bộ phận


8
Tôi thích giải pháp của bạn hơn. Tôi là người mới đến Angular và điều này có vẻ dễ hiểu hơn nhiều từ cách tôi xem web cho đến ngày hôm nay. ai biết được, có thể là thịt sử dụng nhiều khung góc hơn để làm điều đó, nhưng có vẻ như bạn đóng đinh nó với ít dòng mã hơn theo cách hợp lý hơn. cảm ơn!
Gleeb

2
@ProLooser có thể bạn có nghĩa là liên kết này github.com/angular-ui/ui-router ... cái bạn đã dán bị hỏng
simonC

4
Tôi có vấn đề thiết kế tương tự như OP. Có ai đã thử cơ chế trạng thái AngularUI chưa? Tôi khá miễn cưỡng khi sử dụng một thư viện bên thứ 3 khác và tôi thích gắn bó với AngularJS 'cách làm việc'. Nhưng mặt khác, hệ thống định tuyến dường như là điểm yếu của nó ... @PhillipKregg, cuối cùng bạn đã sử dụng cái gì để giải quyết tình huống này?
Sam

4
Bạn có thể chỉ định <div ng-include="'/home/' + tab + '.html'" ng-controller="SubCtrl"></div>để sử dụng bộ điều khiển / phạm vi riêng cho mẫu phụ. Hoặc chỉ định ngControllerchỉ thị bất cứ nơi nào trong (các) mẫu phụ của bạn để sử dụng bộ điều khiển khác nhau cho từng bộ phận.
colllin

2
@DerekAdair dự án khá ổn định (mặc dù số phiên bản) và được sử dụng trong sản xuất ở một vài nơi. Nó ngăn chặn việc tải lại bộ điều khiển không cần thiết và là giải pháp thay thế tốt hơn nhiều cho giải pháp được đề xuất của tôi.
ProLoser

26

Bạn cũng có thể kiểm tra thư viện này cho cùng một mục đích:

http://angular-route-sibution.com

Nó trông giống như những gì bạn đang tìm kiếm, và nó đơn giản hơn nhiều để sử dụng so với ui-router. Từ trang demo :

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 cấp cao nhất:

<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 lồng nhau:

<h4>Section 1</h4>
Section 1 contents.
<div app-view-segment="1"></div>

Artem, của bạn là giải pháp tốt nhất mà tôi tìm thấy cho đến nay! Tôi thích thực tế là bạn mở rộng tuyến đường góc hơn là thay thế nó như ui góc.
LastTribunal

17

Tôi cũng đang vật lộn với các quan điểm lồng nhau trong Angular.

Khi tôi đã nắm giữ bộ định tuyến ui, tôi biết rằng tôi sẽ không bao giờ quay trở lại chức năng định tuyến mặc định góc cạnh.

Dưới đây là một ứng dụng ví dụ sử dụng nhiều cấp độ lồng nhau

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

Như có thể thấy, có 4 khung nhìn chính (view1, view2, view3, view4) và view1 có 3 khung nhìn con.


2
Mục đích của tiêm là $httpProvidergì? Tôi không thấy nó được sử dụng ở bất cứ đâu.
Aaron

@Aaron app.config không kết thúc bằng đoạn mã này và có thể $ httpProvider được sử dụng ở nơi khác
Vlad

4

Bạn có thể sử dụng ng-gộp để tránh sử dụng ng-view lồng nhau.

http://docs.angularjs.org/api/ng/directive/ngInclude
http://plnkr.co/edit/ngdoc:example-example39@snapshot?p=preview

Trang chỉ mục của tôi tôi sử dụng ng-view. Sau đó, trên các trang phụ của tôi mà tôi cần phải có các khung lồng nhau. Tôi sử dụng ng-bao gồm. Bản demo cho thấy một thả xuống. Tôi đã thay thế tôi bằng một liên kết ng-click. Trong hàm tôi sẽ đặt $ scope.template = $ scope.temsheet [0]; hoặc $ scope.template = $ scope.temsheet [1];

$scope.clickToSomePage= function(){
  $scope.template = $scope.templates[0];
};

Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.