Mehrere Controller mit AngularJS in einer einseitigen App

102

Ich möchte wissen, wie mehrere Controller für eine einzelne Seitenanwendung verwendet werden. Ich habe versucht, es herauszufinden, und ich habe Fragen gefunden, die meinen sehr ähnlich sind, aber es gibt nur eine Menge unterschiedlicher Antworten, die ein bestimmtes Problem lösen, bei dem Sie am Ende nicht mehrere Controller für eine einzelne Seiten-App verwenden.

Liegt das daran, dass es nicht ratsam wäre, mehrere Controller für eine einzelne Seite zu verwenden? Oder ist es einfach nicht möglich?

Nehmen wir an, ich habe bereits einen umwerfenden Image-Karussell-Controller auf der Hauptseite, aber dann lerne ich, wie man (sagen wir) Modalitäten verwendet, und ich brauche auch dafür einen neuen Controller (oder alles andere, was ich brauche). Was mache ich dann?

Ich habe einige Antworten auf andere Fragen gesehen, bei denen sie fast die gleichen Fragen stellen wie ich und die Leute antworten: "* OMG. Warum würden Sie das überhaupt tun, tun Sie das einfach ...".

Was ist der beste Weg oder wie machst du das?

Bearbeiten

Viele von Ihnen antworten, nur zwei Controller zu deklarieren und dann mit ng-controller aufzurufen. Ich benutze diesen Code unten und rufe dann MainCtrl mit ng-controller auf.

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

Warum muss ich hier überhaupt einen Controller einstellen, wenn ich ng-controller nur ohne verwenden kann? Das hat mich verwirrt. (und Sie können auf diese Weise nicht zwei Controller hinzufügen, denke ich ...)

TarkaDaal
quelle
Ich glaube nicht, dass ich 2 Controller für eine einzelne HTML-Datei deklarieren kann? wie geht das when: /home, controller: MainCtrl. Kannst du nicht mehr hinzufügen, oder willst du es einfach mit dem ng-Controller aufrufen?
3
@Mosho, du Schritt 1, Schritt 2, fertig, aber erkläre nicht wie oder warum. Wenn es so einfach ist, erklären Sie bitte, wie. Das ist so, als würde man AngularJS verwenden, Fertig. kannst du das näher erläutern? Oder wie es von Juni ist, können sie nicht antworten, kann jemand anderes erklären?
Redfox05

Antworten:

96

Was ist das Problem? Um mehrere Controller zu verwenden, verwenden Sie einfach mehrere ngController-Anweisungen:

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

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

Sie müssen die Controller wie gewohnt in Ihrem Anwendungsmodul verfügbar haben.

Der einfachste Weg, dies zu tun, könnte so einfach sein, wie die Controller-Funktionen wie folgt zu deklarieren:

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

function menuController($scope) {
   // stuff here
}
J. Bruni
quelle
2
Wird das so gemacht? when /home, controller: MainCtrl
8
Wenn Sie Beispiele finden, die die "ng-App" in jedem DIV neben Ihrem "ng-Controller" platzieren, versuchen Sie, nur eine "ng-App" in das "body" -Tag zu verschieben (und löschen Sie das Per-Div ". ng-app "-Tags), wenn nur Ihr erster Controller funktioniert. (Ich erinnere mich daran aus meiner Angular Newbie-Zeit.)
ftexperts
1
Das einzige Problem, das ich bei der Verwendung ng-controllerin mehreren DOM-Elementen hatte, ist beispielsweise in einem Szenario, in dem VIELE Elemente über das DOM gedruckt werden ng-repeat. Nehmen wir an, jeder von ihnen ruft an ng-controller="myController. Aus einigen der Konsolenprotokolle, die ich in meiner Anwendung gesehen habe, wird myControllerneu initialisiert, wobei JEDES Element in dem DOM gerendert wird, das es aufruft. Vielleicht habe ich etwas in meiner speziellen Verwendung vermasselt oder vielleicht außerhalb des Bereichs der OPs Frage, aber neugierig, ob andere das überhaupt erlebt haben ....
Twknab
91

Ich denke, Ihnen fehlt die Bedeutung "Single Page App".

Das bedeutet nicht, dass Sie physisch eine index.htmlHTML-Datei haben, sondern eine Haupt- und mehrere NESTED-HTML-Dateien. Warum also eine einseitige App? Auf diese Weise laden Sie Seiten nicht wie gewohnt (dh Browseraufruf, der die gesamte Seite vollständig aktualisiert), sondern laden nur den Inhaltsteil mit Angular / Ajax. Da Sie das Flackern zwischen den Seitenänderungen nicht sehen, haben Sie den Eindruck, dass Sie sich nicht von der Seite entfernt haben. Sie haben also das Gefühl, auf einer einzigen Seite zu bleiben.

Nun gehe ich davon aus, dass Sie MEHRERE Inhalte für Ihre SINGLE PAGE-App haben möchten: (z. B. Home, Kontakte, Portfolio und Store. Ihre App für einzelne Seiten / mehrere Inhalte (im Winkel) wird folgendermaßen organisiert:

  • index.html: enthält Kopf- <ng-view>und Fußzeile
  • contacts.html: enthält das Kontaktformular (keine Kopf- und Fußzeile)
  • portfolio.html: enthält die Portfolio-Daten (keine Kopf- und Fußzeile)
  • store.html: enthält den Speicher, keine Kopfzeile, keine Fußzeile.

Sie befinden sich im Index, klicken auf das Menü "Kontakte" und was passiert? Angular ersetzt das <ng-view>Tag durch den contacts.htmlCode

Wie erreichen Sie das? mit ngRoute, wie Sie es tun, werden Sie etwas haben wie:

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

Dadurch wird das richtige HTML aufgerufen, das den richtigen Controller an ihn weitergibt (bitte beachten Sie: Geben Sie keine ng-controllerDirektive an, contacts.htmlwenn Sie Routen verwenden ).

Dann können Sie natürlich so viele ng-controller-Anweisungen auf Ihrer contacts.html-Seite deklarieren. Dies sind untergeordnete Controller von ContactCtrl(und erben somit davon). Für eine einzelne Route können Sie jedoch innerhalb der routeProvidereinen einzelnen Controller deklarieren, der als "Vater-Controller der Teilansicht" fungiert.

BEARBEITEN Stellen Sie sich die folgenden Vorlagen / Kontakte vor

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

Das Obige routeProviderinjiziert einen Controller in Ihr enthaltenes Div. Grundsätzlich wird das obige HTML automatisch:

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

Wenn ich sage, dass Sie andere Controller haben können, bedeutet dies, dass Sie Controller wie folgt an innere DOM-Elemente anschließen können:

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

Ich hoffe das klärt die Dinge ein bisschen.

EIN

Adhara
quelle
Wenn Sie also ein zB <div ng-controller="FancyStuffController">in einem Body-Tag deklarieren, auf das bereits ein Controller angewendet wurde, z. B. <body ng-controller="BodyController">funktioniert dies? $apply already in progressIch bekomme Fehler darüber, wann ich das mache, aber ich denke, es hängt mit dpd.js zusammen. Um nicht darauf einzugehen, denke ich, dass es nur zweimal geladen wird oder so, nicht sicher wie, aber meine Verwendung des Controllers versucht möglicherweise, das neu zu laden.
Blamb
1
@ BrianThomas Klar, das sollte funktionieren. Seien Sie vorsichtig: Wenn Sie einen Controller in eine Ansicht einfügen möchten, verwenden Sie den $ routeProvider und schreiben Sie keinen ng-controller in das div-Tag.
Adhara
9

Ich bin gerade dabei, eine Anwendung für eine einzelne Seite zu erstellen. Folgendes habe ich bisher, von dem ich glaube, dass es Ihre Frage beantworten würde. Ich habe eine Basisvorlage (base.html), die ein div mit der ng-viewDirektive enthält. Diese Anweisung teilt Angular mit, wo der neue Inhalt eingefügt werden soll. Beachten Sie, dass ich selbst neu in AngularJs bin, sodass ich keineswegs sage, dass dies der beste Weg ist, dies zu tun.

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>
Austin
quelle
In der Tat verwende ich auch ng-view, damit ich eine main.html in meiner index.html verwenden kann. Aber Sie haben / home und / about und die beiden Controller sind für jeden. Ich habe nur index.html mit ng-view zu meiner main.html. Ich kann nicht zwei Controller für die main.html einstellen, wie Sie es getan habenwhen /home
Werfen
Austin
Nun, ich weiß, wie man mehr setzt when. Ich möchte zwei Controller für eine einzelne Vorlage. Oder vielleicht habe ich falsch verstanden, was Sie mir sagen wollten?
Versuchen Sie, anstelle von Controllern Direktiven zu verwenden. Sie können viele Anweisungen für eine einzelne Vorlage verwenden. Wenn Sie Ihre Controller weiterhin verwenden möchten, finden Sie hier ein Video darüber, wie Direktiven mit Controllern verknüpft werden können: 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 haben Zugriff auf menu div. Und widgetController haben Zugriff auf beide.

Muhammad Awais
quelle
Dies scheint unkompliziert zu sein, hat aber keine positiven Stimmen. Ist das Best Practice oder schlecht?
Redfox05
1
Was Sie tun werden, wenn Sie viele Controller mit mehr als 100 Seiten haben! ... mehrdeutige Praxis.
ArifMustafa
3

Wir können einfach mehr als einen Controller im selben Modul deklarieren. Hier ist ein Beispiel:

  <!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>
Abdallah Okasha
quelle
2

Ich habe nur eine einfache Erklärung der App abgegeben

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

Dann habe ich einen Dienst und zwei Controller gebaut

Für jeden Controller hatte ich eine Zeile im JS

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

Und im HTML habe ich den App-Bereich in einem umgebenden div deklariert

<div ng-app="app">

und jeder Controller-Bereich separat in seinem eigenen umgebenden Div (innerhalb des App-Div)

<div ng-controller="EditableRowCtrl">

Das hat gut funktioniert

pat capozzi
quelle
0

Sie könnten auch alle Ihre Vorlagenansichten in Ihre HTML-Hauptdatei einbetten. Beispielsweise:

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

Auf diese Weise können Sie den Angular-Router weiterhin verwenden, wenn für jede Vorlage ein anderer Controller erforderlich ist. In diesem Beispiel finden Sie ein funktionierendes Beispiel: http://plnkr.co/edit/9X0fT0Q9MlXtHVVQLhgr?p=preview

Auf diese Weise ist die Anwendung, sobald sie vom Server an Ihren Client gesendet wurde, vollständig in sich geschlossen, vorausgesetzt, sie muss keine Datenanforderungen usw. stellen.

Daimonos
quelle