Tek sayfalı uygulamada AngularJS ile birden fazla kontrolör


102

Tek sayfalı bir uygulama için birden çok denetleyicinin nasıl kullanılacağını bilmek istiyorum. Bunu anlamaya çalıştım ve benimkine çok benzer sorular buldum, ancak tek sayfalık bir uygulama için birden fazla denetleyici kullanmadığınız belirli bir sorunu çözen yalnızca bir ton farklı yanıt var.

Tek bir sayfa için birden fazla denetleyici kullanmanın akıllıca olmayacağı için mi? Yoksa bu mümkün değil mi?

Diyelim ki ana sayfada çalışan harika bir görüntü atlıkarınca denetleyicim var, ancak sonra modları nasıl kullanacağımı (diyelim) öğreniyorum ve bunun için de yeni bir denetleyiciye ihtiyacım var (veya bir denetleyiciye ihtiyacım olan başka bir şey). O zaman ne yapacağım

Benimle neredeyse aynı şeyleri sordukları diğer sorulara bazı cevaplar gördüm ve insanlar "* Aman Tanrım. Bunu neden yapasın ki, sadece bunu yap ...".

En iyi yol nedir veya bunu nasıl yaparsınız?

Düzenle

Birçoğunuz sadece iki denetleyici ilan etmeyi ve ardından onu aramak için ng-denetleyiciyi kullanmayı yanıtlıyorsunuz. Aşağıdaki kod parçasını kullanıyorum ve ardından ng-controller ile MainCtrl çağırıyorum.

app.config(function($routeProvider, $locationProvider) {                        
  $routeProvider                                                                
       .when('/', {                                            
         templateUrl: "templates/main.html",                                               
         controller:'MainCtrl',                                
        })                                                                      
        .otherwise({                      
            template: 'does not exists'   
        });      
});

Ng-denetleyiciyi onsuz kullanabiliyorsam neden burada bir denetleyici ayarlamam gerekiyor? Kafamı karıştıran bu. (ve bu şekilde iki denetleyici ekleyemezsiniz, sanırım ...)


Tek bir .html dosyası için 2 denetleyici tanımlayabileceğimi sanmıyorum? bu nasıl yapılır? when: /home, controller: MainCtrl. bundan daha fazlasını ekleyemez misiniz, yoksa onu sadece ng-kontrolör ile aramak mı istiyorsunuz?

3
@Mosho, adım 1, adım 2, bitti, ancak nasıl veya neden olduğunu açıklamayın. Bu kadar basitse, lütfen nasıl olduğunu açıklayın. Bu AngularJS kullan, Done demek gibi. detaylandırabilir / açıklayabilir misiniz? Ya da hazirandan itibaren cevap vermeyebilirler, başkası açıklayabilir mi?
redfox05

Yanıtlar:


96

Sorun nedir? Birden çok denetleyici kullanmak için birden çok ngController yönergesi kullanın:

<div class="widget" ng-controller="widgetController">
    <p>Stuff here</p>
</div>

<div class="menu" ng-controller="menuController">
    <p>Other stuff here</p>
</div>

Denetleyicileri her zamanki gibi uygulama modülünüzde bulundurmanız gerekecektir.

Bunu yapmanın en basit yolu, denetleyici işlevlerini şu şekilde bildirmek kadar basit olabilir:

function widgetController($scope) {
   // stuff here
}

function menuController($scope) {
   // stuff here
}

2
Bu böyle mi yapılır? Bunu kullanıyorumwhen /home, controller: MainCtrl

8
Her DIV'de "ng-denetleyicinizin" yanına "ng-app" koyan örneklerden çıkıyorsanız, "body" etiketine yalnızca bir "ng-app" eklemeyi deneyin (ve per-div'i silin ng-app "etiketleri) yalnızca ilk denetleyiciniz çalışıyorsa. (Bunu Angular yeni başlayan günlerimden hatırlıyorum.)
ftexperts

1
ng-controllerBirden çok DOM öğesinde kullanmakla ilgili yaşadığım tek sorun , DOM'a aracılığıyla yazdırılan BİRÇOK öğenin olduğu bir senaryoda olduğu söylenebilir ng-repeat. Diyelim ki bunların her biri bir çağrı yapıyor ng-controller="myController. Uygulamamda gördüğüm konsol günlüklerinden bazılarından, myControllerDOM'da işlenen EACH öğesi onu çağırarak yeniden başlatıyor ... Belki kendi kullanımımda bir şeyleri batırdım veya belki de OP'lerin kapsamı dışında soru, ama başkalarının da bunu yaşayıp yaşamadığını merak ediyorum ....
twknab

91

"Tek sayfalı uygulama" anlamını kaçırdığınızı düşünüyorum.

Bu, fiziksel olarak bir .html'ye sahip olacağınız anlamına gelmez, bunun yerine bir main index.html ve birkaç NESTED .html dosyanız . Peki neden tek sayfalık uygulama? Çünkü bu şekilde sayfaları standart yolla (yani, tüm sayfayı tamamen yenileyen tarayıcı çağrısı) değil, yalnızca içerik bölümünü Angular / Ajax kullanarak yüklersiniz. Sayfa değişiklikleri arasında titreşimi görmediğiniz için, sayfadan hareket etmemişsiniz izlenimi edinirsiniz. Böylece tek bir sayfada kalıyormuş gibi hissedersiniz.

Şimdi, TEK SAYFA uygulamanız için ÇOKLU içeriğe sahip olmak istediğinizi varsayıyorum: (örneğin) ev, kişiler, portföy ve mağaza. Tek sayfanız / çoklu içerik uygulamanız (açısal yol) şu şekilde organize edilecektir:

  • index.html: başlık içerir, <ng-view> ve altbilgi
  • contacts.html: iletişim formunu içerir (üst bilgi yok, alt bilgi yok)
  • portfolio.html: portföy verilerini içerir (üst bilgi yok alt bilgi yok)
  • store.html: mağazayı içerir, üst bilgi yok, alt bilgi yok.

Dizindesiniz, "kişiler" adlı menüye tıklarsınız ve ne olur? Angular, <ng-view>etiketi contacts.htmlkodla değiştirir

Bunu nasıl başarırsınız? ile ngRoute, yaptığınız gibi, aşağıdaki gibi bir şeye sahip olacaksınız:

app.config(function($routeProvider, $locationProvider) {                        
  $routeProvider                                                                
       .when('/', {                                            
         templateUrl: "templates/index.html",                                               
         controller:'MainCtrl',                                
        })
        .when('/contacts', {                                            
         templateUrl: "templates/contacts.html",                                               
         controller:'ContactsCtrl',                                
        })                                                                 
        .otherwise({                      
            template: 'does not exists'   
        });      
});

Bu, doğru denetleyiciyi ona geçiren doğru html'yi çağıracaktır (lütfen dikkat: rotaları kullanıyorsanız yönergeyi belirtmeyinng-controllercontacts.html )

Ardından, elbette, contact.html sayfanızın içinde olabildiğince çok ng-controller yönergesi beyan edebilirsiniz. Bunlar alt denetleyiciler olacaktır ContactCtrl(dolayısıyla ondan miras alacaklardır ). Ancak tek bir yol için, içinde routeProvider, "Kısmi görünümün Baba denetleyicisi" olarak hareket edecek tek bir Denetleyici ilan edebilirsiniz.

DÜZENLE Aşağıdaki şablonları / kişiler.html'yi hayal edin

<div>
    <h3>Contacts</h3>
    <p>This is contacts page...</p>
</div>

yukarıdakiler routeProvider, içeren div'inize bir denetleyici enjekte edecektir. Temel olarak yukarıdaki html otomatik olarak şöyle olur:

<div ng-controller="ContactsCtrl">
    <h3>Contacts</h3>
    <p>This is contacts page...</p>
</div>

Başka denetleyicilere sahip olabileceğinizi söylediğimde, denetleyicileri aşağıdaki gibi iç DOM öğelerine bağlayabileceğiniz anlamına gelir:

<div>
    <h3>Contacts</h3>
    <p ng-controller="anotherCtrl">Hello {{name}}! This is contacts page...     
    </p>
</div>

Umarım bu işleri biraz açıklığa kavuşturur.

Bir


Öyleyse, <div ng-controller="FancyStuffController">zaten bir denetleyici eklenmiş olan bir gövde etiketinin içinde, örneğin <body ng-controller="BodyController">bu çalışacak mı? $apply already in progressBunu ne zaman yaptığımla ilgili hatalar alıyorum , ancak bunun dpd.js ile ilgili olduğunu düşünüyorum. Buna girmemek için, sanırım sadece iki kez yüklüyor veya başka bir şey, nasıl olduğundan emin değilim, ancak denetleyiciyi kullanımım onu ​​yeniden yüklemeye çalışıyor olabilir.
2015'i

1
@BrianThomas Elbette, bu işe yaramalı. Dikkatli olun: Bir görünümde bir denetleyici enjekte etmek istiyorsanız, $ routeProvider'ı kullanın, ng-controller'ı div etiketine yazmayın.
Adhara

9

Şu anda tek sayfalık bir uygulama oluşturma sürecindeyim. İşte şu ana kadar sorunuzu yanıtlayacağına inandığım şeyler. ng-viewİçinde yönerge olan bir div bulunan bir temel şablonum (base.html) var . Bu yönerge, yeni içeriğin nereye yerleştirileceğini açısal olarak anlatır. Angularjs'de yeniyim, bu yüzden hiçbir şekilde bunu yapmanın en iyi yolu olduğunu söylemiyorum.

app = angular.module('myApp', []);                                                                             

app.config(function($routeProvider, $locationProvider) {                        
  $routeProvider                                                                
       .when('/home/', {                                            
         templateUrl: "templates/home.html",                                               
         controller:'homeController',                                
        })                                                                      
        .when('/about/', {                                       
            templateUrl: "templates/about.html",     
            controller: 'aboutController',  
        }) 
        .otherwise({                      
            template: 'does not exists'   
        });      
});

app.controller('homeController', [              
    '$scope',                              
    function homeController($scope,) {        
        $scope.message = 'HOME PAGE';                  
    }                                                
]);                                                  

app.controller('aboutController', [                  
    '$scope',                               
    function aboutController($scope) {        
        $scope.about = 'WE LOVE CODE';                       
    }                                                
]); 

base.html

<html>
<body>

    <div id="sideMenu">
        <!-- MENU CONTENT -->
    </div>

    <div id="content" ng-view="">
        <!-- Angular view would show here -->
    </div>

<body>
</html>

gerçekten de, index.html dosyamda main.html kullanabilmek için ng-view kullanıyorum. ama / home ve / about var ve her biri için iki denetleyici var. Main.html dosyamda yalnızca ng-view ile index.html var. Main.html için sizin yaptığınız gibi iki denetleyici ayarlayabiliyorumwhen /home

Bu gönderinin ilk cevabına bir göz atın: stackoverflow.com/questions/17354568/…
Austin

peki, daha fazlasını nasıl ayarlayacağımı biliyorum when. Tek bir şablon için iki denetleyici istiyorum. Ya da dostum, bana söylemeye çalıştığını yanlış anladım?

Denetleyicileri kullanmak yerine yönergeleri kullanmayı deneyin. Tek bir şablon üzerinde birçok yönerge kullanabilirsiniz. Yine de denetleyicilerinizi kullanmak istiyorsanız, yönergelerin denetleyicilerle nasıl bağlantı kurabileceğine dair bir video: egghead.io/lessons/angularjs-directives-talking-to-controllers
Austin

6
<div class="widget" ng-controller="widgetController">
    <p>Stuff here</p>
</div>

<div class="menu" ng-controller="menuController">
    <p>Other stuff here</p>
</div>
///////////////// OR ////////////


  <div class="widget" ng-controller="widgetController">
    <p>Stuff here</p>
    <div class="menu" ng-controller="menuController">
        <p>Other stuff here</p>
    </div>
</div>

menuController menü div erişimi vardır. Ve widgetController her ikisine de erişebilir.


Bu basit görünüyor, ancak olumlu oyları yok. Bu en iyi uygulama mı yoksa kötü mü?
redfox05

1
Ne yaparsınız, çok sayıda sayfada 100'den fazla denetleyiciniz varsa! ... belirsiz uygulama.
ArifMustafa

3

Aynı modülde birden fazla Denetleyici ilan edebiliriz. İşte bir örnek:

  <!DOCTYPE html>
    <html>

    <head>
       <script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.6.4/angular.min.js">
       </script>
      <title> New Page </title>


    </head> 
    <body ng-app="mainApp"> <!-- if we remove ng-app the add book button [show/hide] will has no effect --> 
      <h2> Books </h2>

    <!-- <input type="checkbox" ng-model="hideShow" ng-init="hideShow = false"></input> -->
    <input type = "button" value = "Add Book"ng-click="hideShow=(hideShow ? false : true)"> </input>
     <div ng-app = "mainApp" ng-controller = "bookController" ng-if="hideShow">
             Enter book name: <input type = "text" ng-model = "book.name"><br>
             Enter book category: <input type = "text" ng-model = "book.category"><br>
             Enter book price: <input type = "text" ng-model = "book.price"><br>
             Enter book author: <input type = "text" ng-model = "book.author"><br>


             You are entering book: {{book.bookDetails()}}
     </div>

    <script>
             var mainApp = angular.module("mainApp", []);

             mainApp.controller('bookController', function($scope) {
                $scope.book = {
                   name: "",
                   category: "",
                   price:"",
                   author: "",


                   bookDetails: function() {
                      var bookObject;
                      bookObject = $scope.book;
                      return "Book name: " + bookObject.name +  '\n' + "Book category: " + bookObject.category + "  \n" + "Book price: " + bookObject.price + "  \n" + "Book Author: " + bookObject.author;
                   }

                };
             });
    </script>

    <h2> Albums </h2>
    <input type = "button" value = "Add Album"ng-click="hideShow2=(hideShow2 ? false : true)"> </input>
     <div ng-app = "mainApp" ng-controller = "albumController" ng-if="hideShow2">
             Enter Album name: <input type = "text" ng-model = "album.name"><br>
             Enter Album category: <input type = "text" ng-model = "album.category"><br>
             Enter Album price: <input type = "text" ng-model = "album.price"><br>
             Enter Album singer: <input type = "text" ng-model = "album.singer"><br>


             You are entering Album: {{album.albumDetails()}}
     </div>

    <script>
             //no need to declare this again ;)
             //var mainApp = angular.module("mainApp", []);

             mainApp.controller('albumController', function($scope) {
                $scope.album = {
                   name: "",
                   category: "",
                   price:"",
                   singer: "",

                   albumDetails: function() {
                      var albumObject;
                      albumObject = $scope.album;
                      return "Album name: " + albumObject.name +  '\n' + "album category: " + albumObject.category + "\n" + "Book price: " + albumObject.price + "\n" + "Album Singer: " + albumObject.singer;
                   }
                };
             });
    </script>

    </body>
    </html>

2

Sadece uygulamanın basit bir beyanını koydum

var app = angular.module("app", ["xeditable"]);

Sonra bir servis ve iki kontrolcü yaptım

Her denetleyici için JS'de bir satırım vardı

app.controller('EditableRowCtrl', function ($scope, CRUD_OperService) {

HTML'de, uygulama kapsamını çevreleyen bir div'de tanımladım

<div ng-app="app">

ve her bir denetleyici kapsamı kendi çevreleyen div içinde ayrı ayrı (uygulama div içinde)

<div ng-controller="EditableRowCtrl">

Bu iyi çalıştı


0

Ayrıca, tüm şablon görünümlerinizi ana html dosyanıza da yerleştirebilirsiniz. Örneğin:

<body ng-app="testApp">
  <h1>Test App</h1>
  <div ng-view></div>
  <script type = "text/ng-template" id = "index.html">
    <h1>Index Page</h1>
    <p>{{message}}</p>
  </script>
  <script type = "text/ng-template" id = "home.html">
    <h1>Home Page</h1>
    <p>{{message}}</p>
  </script>
</body>

Bu şekilde, her şablon farklı bir denetleyici gerektiriyorsa, açısal yönlendiriciyi yine de kullanabilirsiniz. Çalışan bir örnek için bu ayrıntıya bakın http://plnkr.co/edit/9X0fT0Q9MlXtHVVQLhgr?p=preview

Bu şekilde, uygulama sunucudan istemcinize gönderildikten sonra, herhangi bir veri talebinde bulunmasına vb. Gerek olmadığı varsayılarak tamamen bağımsızdır.

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.