Kısmi ve şablonların karmaşık iç içe yerleştirilmesi


503

Benim sorum, AngularJS uygulamasında şablonların ( kısmi olarak da adlandırılır ) karmaşık iç içe geçmesiyle nasıl başa çıkılacağını içerir .

Durumumu tarif etmenin en iyi yolu, oluşturduğum bir görüntü ile:

Açısal JS Sayfası Diyagramı

Gördüğünüz gibi, bu çok sayıda iç içe model ile oldukça karmaşık bir uygulama olma potansiyeline sahiptir.

Uygulama tek sayfadır, bu nedenle DOM'dang-view özniteliğe sahip bir div öğesi içeren bir index.html yükler .

Daire 1 için , ilgili şablonları yükleyen Birincil gezinme olduğunu görürsünüz ng-view. Bunu $routeParamsana uygulama modülüne geçerek yapıyorum . İşte benim app ne bir örnek:

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

    }]);

Daire 2'de , içine yüklenen şablonun ng-viewek bir alt gezinmesi vardır . Bu alt nav daha sonra altındaki alana şablonlar yüklemesi gerekir - ama ng-view zaten kullanıldığından, bunu nasıl yapacağımdan emin değilim.

İlk şablonun içine ek şablonlar ekleyebileceğimi biliyorum, ancak bu şablonların hepsi oldukça karmaşık olacak. Uygulamanın güncellenmesini kolaylaştırmak ve alt öğelerine erişmek için yüklenecek ana şablona bağımlı olmamak için tüm şablonları ayrı tutmak istiyorum.

Daire 3'te , işlerin daha da karmaşıklaştığını görebilirsiniz. Alt gezinme şablonlarının , kendi şablonlarını da daire 4'teki alana yüklemesi gereken 2. bir alt gezinme özelliğine sahip olma potansiyeli vardır.

Bir AngularJS uygulamasını, şablonların bu kadar karmaşık iç içe yerleştirilmesiyle başa çıkacak ve hepsini birbirinden ayrı tutacak şekilde nasıl yapılandırılır?


3
Hala bu konuyu takip ediyorsanız, bunu ele almak için yeni bir AngularUI projesine bir bağlantı ekledim ve cevabım için bir yönerge gerekmeden alt yollar tarafından desteklenen üçüncü bir demo ekledim.
ProLoser


82
Uzun zamandır gördüğüm en güzel soru :)
Mark Nadig

2
kabul! Mockup kullanımını seviyorum
Bryan Hong

4
Burada doğrudan soruya alternatiflere bağlantılar eklemek harika olurdu. github.com/angular-ui/ui-router github.com/artch/angular-route-segment github.com/dotJEM/angular-routing
Jens

Yanıtlar:


171

Şu anda sadece bir ngView yönergesine sahip olabildiğiniz için ... İç içe yön denetimleri kullanıyorum. Bu, aralarında şablon oluşturma ve devralma (veya ayırma) kapsamlarını ayarlamanıza olanak tanır. Bunun dışında ng-switch kullanıyorum, hatta $ routeParams'dan gelenlere göre hangi kontrolleri görüntülediğimi seçmek için sadece ng-show kullanıyorum.

DÜZENLE Size neden bahsettiğim hakkında bir fikir vermek için bazı sahte kod örnekleri. Yuvalanmış bir alt gezinme ile.

İşte ana uygulama sayfası

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

Alt navigasyon direktifi

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

alt gezinme şablonu

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

ana sayfa şablonu (birincil gezinme bölmesinden)

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

Ana sayfa için kontrolör. (birincil gezinme bölmesinden)

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

Bir Alt Alan Yönergesi

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

9
ProLoser'ın çözümünü daha iyi seviyorum, uygulamamızda böyle bir şey yapıyoruz ve iyi çalıştı. Blesh'ın çözümü ile ilgili sorun, direktiflere giren kontrolör kodudur. Genellikle bir yönergede belirttiğiniz denetleyici, giriş ve diğer yönergelerle yakından çalışan ex: ngModelCtrl yönergesiyle yakından çalışan bir denetleyicidir. Denetleyici kodunu bir yönerge içine koymak sizin durumunuzda bir kod kokusu olur, aslında bağımsız bir denetleyicidir.
ChrisOdney

@blesh, güzel! Gerçekten iyi açıklanmış gibi görünüyor ama iyi bir JS programcısı ve AngularJS acemi olarak ben iyi yakalayamaz ... Ben ve topluluk gerçekten bu yaklaşımı kullanarak çalışan bir örnek bir JSFiddle bağlantı zevk olurdu. Etrafında kazmak kolay olurdu! :) Teşekkürler
Roger Barreto

8
Bence bu çözüm, 'iç içe bakış işe yaramadı' şeklinde herhangi bir soruya ilk cevap olmalıdır. Sadece ui-router vb kullanmak yerine Açısal ideolojiye çok daha yakın olduğu için teşekkürler.
Sergei Panfilov

Peki cevap direktifler mi?
Marc M.7

alt-nav öğelerini vurgulamak için bunu kullanabilirsiniz: coder1.com/articles/angularjs-managing-active-nav-elements bu bunu yapmanın iyi bir yolu mu?
14'te

198

GÜNCELLEME: Bu sorunu çözmek için AngularUI'nin yeni projesine göz atın


Alt bölümler için ng-include dizelerini kullanmak kadar kolaydır:

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

Veya her yerde alt sayfalara bağlantı olması durumunda bir nesne oluşturabilirsiniz:

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

Ya da kullanabilirsiniz $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>

Ayrıca bir kısmi denetleyiciyi her bir kısmi en üst düzeye yerleştirebilirsiniz


8
Çözümünü daha çok seviyorum. Ben Açısal bir yeniyim ve bu çok bugüne kadar web görmek nasıl daha anlaşılır görünüyor. kim bilir, blesh bunu yapmak için daha fazla açısal çerçeve kullanır, ancak daha az kod satırı ile daha mantıklı bir şekilde çivilenmiş gibi görünüyor. Teşekkürler!
Gleeb

2
@ProLooser belki bu bağlantıyı kast ettiniz github.com/angular-ui/ui-router ... yapıştırdığınız bir kopuk
simonC

4
OP ile aynı tasarım sorununu yaşıyorum. AngularUI durum mekanizmasını deneyen var mı? Başka bir üçüncü taraf kütüphanesi kullanmakta oldukça isteksizim ve AngularJS'in 'bir şeyler yapma tarzına' bağlı kalmayı tercih ederim. Ancak öte yandan, yönlendirme sistemi Aşil topuğu gibi görünüyor ... @PhillipKregg, bu senaryoyu çözmek için neyi kullandınız?
Sam

4
<div ng-include="'/home/' + tab + '.html'" ng-controller="SubCtrl"></div>Alt şablon için ayrı bir denetleyici / kapsam kullanmak için belirtebilirsiniz . Ya da ngControllerher kısmi için farklı bir denetleyici kullanmak için direktifi alt şablon (larınız) içinde herhangi bir yerde belirtin .
colllin

2
@DerekAdair proje oldukça kararlı (sürüm numarasına rağmen) ve birkaç yerde üretimde kullanılıyor. Gereksiz denetleyicinin yeniden yüklenmesini önler ve önerilen çözümüme çok daha iyi bir alternatiftir.
ProLoser

26

Bu kütüphaneye aynı amaçla da ödeme yapabilirsiniz:

http://angular-route-segment.com

Aradığınıza benziyor ve kullanımı ui-yönlendiriciden çok daha basit. Gönderen demo sitesinde :

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

Üst düzey 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>

İç içe HTML:

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

Artem, seninki bugüne kadar bulduğum en iyi çözüm! Açısal ui'nin yerine açısal rotayı uzatmak yerine açmayı seviyorum.
LastTribunal

17

Ben de Angular'da iç içe geçmiş manzaralarla uğraşıyordum.

Bir kez ui-router tuttuğumda, açısal varsayılan yönlendirme fonksiyonuna asla geri dönmeyeceğimi biliyordum.

Aşağıda, birden çok görünüm iç içe yerleştirme düzeyi kullanan örnek bir uygulama yer almaktadır

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

Görülebileceği gibi 4 ana görünüm vardır (view1, view2, view3, view4) ve view1 3 çocuk manzarasına sahiptir.


2
Enjekte etmenin amacı nedir $httpProvider? Hiçbir yerde kullanıldığını görmüyorum.
Aaron

@Aaron app.config bu kod parçasıyla bitmez ve $ httpProvider başka bir yerde kullanılır
Vlad

4

Yuvalanmış görünümler kullanmaktan kaçınmak için ng-include komutunu kullanabilirsiniz.

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

Dizin sayfam ng-view kullanıyorum. Sonra alt sayfalarımda iç içe çerçeveler olması gerekir. Ng-include kullanıyorum. Demo bir açılır menü gösterir. Benimkini bir link ng-click ile değiştirdim. İşlevde $ scope.template = $ scope.templates [0]; veya $ scope.template = $ scope.templates [1];

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

Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.