부분 및 템플릿의 복잡한 중첩


503

내 질문은 AngularJS 응용 프로그램에서 템플릿의 복잡한 중첩 ( 부분적 이라고도 함 )을 다루는 방법에 관한 것 입니다.

내 상황을 설명하는 가장 좋은 방법은 내가 만든 이미지를 사용하는 것입니다.

AngularJS 페이지 다이어그램

보시다시피 이것은 많은 중첩 모델이있는 상당히 복잡한 응용 프로그램이 될 수 있습니다.

응용 프로그램은 단일 페이지이므로 속성이 있는 DOM에 div 요소가 포함 된 index.html 을 로드 ng-view합니다.

서클 1 의 경우 적절한 템플릿을에로드하는 기본 탐색이 있음을 알 수 ng-view있습니다. $routeParams기본 앱 모듈 로 전달 하여이 작업을 수행하고 있습니다. 다음은 내 앱에있는 예입니다.

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

    }]);

서클 2 에서에로드되는 템플릿 ng-view에는 추가 하위 탐색이 있습니다. 이 하위 탐색은 템플릿을 그 아래 영역에로드해야하지만 ng-view가 이미 사용 중이므로 어떻게해야할지 모르겠습니다.

첫 번째 템플릿에 추가 템플릿을 포함시킬 수 있지만 이러한 템플릿은 모두 매우 복잡합니다. 응용 프로그램을 쉽게 업데이트하고 자식 템플릿에 액세스하기 위해 부모 템플릿을로드하지 않아도되도록 모든 템플릿을 별도로 유지하고 싶습니다.

서클 3에서는 상황이 더욱 복잡 해지는 것을 볼 수 있습니다. 하위 탐색 템플릿이 미칠 가능성이있는 2 차 하위 탐색 의 영역으로뿐만 아니라 자신의 템플릿을로드해야합니다 원 (4)

AngularJS 앱을 구성하여 복잡한 템플릿 중첩을 처리하면서 템플릿을 서로 분리하여 유지하는 방법은 무엇입니까?


3
이 스레드를 계속 따르는 경우 새 AngularUI 프로젝트에 대한 링크를 추가하여이 문제를 해결하고 세 번째 데모에서 내 대답에 대한 지시 없이도 서브 루트에 의해 구동됩니다.
ProLoser

2
이건 어때? bennadel.com/blog/…
ericbae

82
내가 본 것 중 가장 예쁜 질문 :)
Mark Nadig

2
동의했다! 모형 사용을 좋아합니다
Bryan Hong

4
여기 질문에 직접 대안에 대한 링크를 추가하는 것이 좋습니다. github.com/angular-ui/ui-router github.com/artch/angular-route-segment github.com/dotJEM/angular-routing
Jens

답변:


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>

하위 탐색 지시문

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

하위 탐색을위한 템플릿

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

기본 페이지의 템플릿 (기본 탐색 메뉴에서)

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

메인 페이지의 컨트롤러. (기본 탐색 메뉴에서)

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

하위 영역에 대한 지시문

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

9
나는 ProLoser의 솔루션을 더 좋아합니다. 우리는 앱에서 이와 같은 일을하고 잘 작동했습니다. blesh 솔루션의 문제점은 지시어에 들어가는 컨트롤러 코드입니다. 일반적으로 지시문에 지정하는 컨트롤러는 입력 및 기타 지시문과 밀접하게 작동하는 ex에 대한 지시문과 밀접하게 작동하는 컨트롤러입니다. 귀하의 경우 컨트롤러 코드를 지시문에 넣으면 코드 냄새가 나기 때문에 실제로는 독립적 인 컨트롤러입니다.
ChrisOdney

@blesh, 좋은! 정말 잘 설명 된 것처럼 보이지만 AngularJS의 훌륭한 JS 프로그래머 및 초보자로서 나는 그것을 잘 잡아낼 것입니다 ... 나와 커뮤니티는 실제로 그 접근 방식을 사용하여 작업 샘플에 대한 JSFiddle 링크를 즐길 것입니다. 그것을 파고 이해하기 쉬울 것입니다! :) 감사합니다
로저 바레토

8
이 솔루션은 '중첩보기가 작동하지 않습니다'라는 질문에 대한 첫 번째 답변이어야한다고 생각합니다. ui-router 등을 사용하는 대신 Angular 이데올로기에 훨씬 가깝기 때문에 감사합니다.
Sergei Panfilov

대답은 지시어입니까?
Marc M.

사용할 수있는 하위 탐색 항목을 강조 표시하려면 coder1.com/articles/angularjs-managing-active-nav-elements 이 방법이 좋은 방법입니까?
escapedcat

198

업데이트 : 이 문제를 해결하기 위해 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>

또는 모든 장소의 하위 페이지에 대한 링크가있는 경우 객체를 만들 수 있습니다.

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

또는 당신은 사용할 수 있습니다 $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>

ng-controller를 각 부분의 최상위 레벨에 놓을 수도 있습니다


8
나는 당신의 해결책을 더 좋아합니다. 나는 Angular에 익숙하지 않으며 이것이 오늘날까지 웹을 보는 방식에서 훨씬 더 이해할 수있는 것처럼 보입니다. 알다시피, 육체는 더 많은 각도 프레임 워크를 사용하여 그것을 할 수 있지만 더 합리적인 방식으로 더 적은 코드 줄로 못 박은 것처럼 보입니다. 감사!
Gleeb

2
@ProLooser 어쩌면 당신은이 링크의 의미 github.com/angular-ui/ui-router를 붙여 넣은 사람이 고장 ...
simonC

4
OP와 동일한 디자인 문제가 있습니다. 누구나 AngularUI 상태 메커니즘을 사용해 보셨습니까? 또 다른 타사 라이브러리를 사용하는 것을 꺼려하고 AngularJS의 '일을하는 길'을 고수하고 싶습니다. 그러나 다른 한편으로, 라우팅 시스템은 Achilles의 발 뒤꿈치 인 것 같습니다 ... @PhillipKregg,이 시나리오를 해결하기 위해 무엇을 사용하게 되었습니까?
Sam

4
<div ng-include="'/home/' + tab + '.html'" ng-controller="SubCtrl"></div>서브 템플릿에 별도의 컨트롤러 / 스코프를 사용하도록 지정할 수 있습니다 . 또는 ngController서브 템플릿 내 어디에서나 지시문을 지정하여 각 부분에 대해 다른 컨트롤러를 사용하십시오.
colllin

2
@DerekAdair 프로젝트는 상당히 안정적이고 (버전 번호 임에도 불구하고) 몇 곳에서 생산에 사용됩니다. 불필요한 컨트롤러 재로드를 방지하고 제안 된 솔루션의 훨씬 더 나은 대안입니다.
ProLoser

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

최상위 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>

중첩 된 HTML :

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

Artem, 당신의 것이 제가 지금까지 찾은 최고의 솔루션입니다! 나는 당신이 각도 ui처럼 그것을 대체하기보다는 각도 경로를 확장한다는 사실을 좋아합니다.
LastTribunal

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

보시다시피 4 개의 주요 뷰 (view1, view2, view3, view4)가 있으며 view1에는 3 개의 자식 뷰가 있습니다.


2
주사의 목적은 무엇입니까 $httpProvider? 어디서나 사용되지 않습니다.
Aaron

@Aaron app.config는이 코드로 끝나지 않으며 $ httpProvider 가 다른 곳에서 사용될 수 있습니다.
Vlad

4

중첩 된 ng-view 사용을 피하기 위해 ng-include를 사용할 수 있습니다.

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

내 색인 페이지는 ng-view를 사용합니다. 그런 다음 하위 페이지에서 중첩 프레임이 필요합니다. ng-include를 사용합니다. 데모는 드롭 다운을 보여줍니다. 링크 ng-click으로 교체했습니다. 함수에 $ scope.template = $ scope.templates [0]; 또는 $ scope.template = $ scope.templates [1];

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

당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.