web-dev-qa-db-fra.com

Plusieurs contrôleurs avec AngularJS dans une seule page

Je veux savoir comment utiliser plusieurs contrôleurs pour une application à une seule page. J'ai essayé de le comprendre et j'ai trouvé des questions très similaires aux miennes, mais il y a une tonne de réponses différentes qui résolvent un problème spécifique dans lequel vous n'utilisez pas plusieurs contrôleurs pour une application d'une seule page.

Est-ce parce qu'il ne serait pas sage d'utiliser plusieurs contrôleurs pour une seule page? Ou est-ce simplement impossible?

Disons que j'ai déjà un contrôleur de carrousel d'images kick-ass qui travaille sur la page principale, mais j'apprends ensuite comment utiliser (disons) des modaux et j'ai besoin d'un nouveau contrôleur pour cela aussi (ou de toute autre chose pour laquelle j'ai besoin d'un contrôleur). Que vais-je faire alors?

J'ai vu certaines réponses à d'autres questions où ils demandent à peu près les mêmes choses que moi et les gens répondent "* OMG. Pourquoi voudriez-vous même faire cela, faites-le simplement ...".

Quel est le meilleur moyen ou comment le fais-tu?

Éditer

Vous êtes nombreux à vouloir déclarer deux contrôleurs, puis utiliser ng-controller pour l'appeler. J'utilise ce morceau de code ci-dessous et appelle ensuite MainCtrl avec ng-controller.

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

Pourquoi ai-je même besoin de configurer un contrôleur ici si je peux simplement utiliser ng-controller sans ce contrôleur? C'est ce qui m'a confondu. (et vous ne pouvez pas ajouter deux contrôleurs de cette façon, je pense ...)

98
user2539369

Quel est le problème? Pour utiliser plusieurs contrôleurs, utilisez simplement plusieurs directives ngController:

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

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

Les contrôleurs doivent être disponibles dans votre module d’application, comme d’habitude.

Le moyen le plus simple de le faire pourrait être aussi simple que de déclarer les fonctions du contrôleur comme ceci:

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

function menuController($scope) {
   // stuff here
}
92
J. Bruni

Je pense que vous manquez la signification de "application à page unique".

Cela ne signifie pas que vous aurez physiquement un fichier .html, mais un fichier principal index.html et plusieurs fichiers .html NESTED. Alors pourquoi une seule page? Parce que de cette façon, vous ne chargez pas les pages de la manière standard (c'est-à-dire un appel de navigateur qui rafraîchit complètement la page), mais vous ne chargez que la partie contenu en utilisant Angular/Ajax. Puisque vous ne voyez pas le scintillement entre les changements de page, vous avez l’impression que vous n’avez pas quitté la page. Ainsi, vous vous sentez comme si vous restiez sur une seule page.

Maintenant, je suppose que vous voulez avoir plusieurs contenus pour votre application SINGLE PAGE: (par exemple, la maison, les contacts, le portfolio et le magasin). Votre application de page unique/à contenus multiples (la manière angular) sera organisée de la manière suivante:

  • index.html: contient l'en-tête, <ng-view> et le pied de page
  • contacts.html: contient le formulaire de contact (pas d'en-tête, pas de pied de page)
  • portfolio.html: contient les données du portefeuille (pas d'en-tête ni de pied de page)
  • store.html: contient le magasin, pas d'en-tête ni de pied de page.

Vous êtes dans l'index, vous cliquez sur le menu "Contacts" et que se passe-t-il? Angular remplace la balise <ng-view> par le code contacts.html

Comment y parvenez-vous? avec ngRoute, comme vous le faites, vous obtiendrez quelque chose comme:

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

Ceci appellera le bon html en lui passant le bon contrôleur (veuillez noter: ne spécifiez pas la directive ng-controller dans contacts.html si vous utilisez des routes)

Ensuite, bien sûr, vous pouvez déclarer autant de directives ng-controller dans votre page contacts.html. Ceux-ci seront des contrôleurs enfants de ContactCtrl (en héritant ainsi). Mais pour un seul itinéraire, à l'intérieur de la routeProvider, vous pouvez déclarer un seul contrôleur qui agira en tant que "contrôleur père de la vue partielle".

EDIT Imaginez les modèles/contacts.html suivants

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

le routeProvider ci-dessus va injecter un contrôleur dans votre div contenant. Fondamentalement, le code HTML ci-dessus devient automatiquement:

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

Quand je dis que vous pouvez avoir d'autres contrôleurs, cela signifie que vous pouvez connecter des contrôleurs à des éléments internes du DOM, comme suit:

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

J'espère que cela clarifie un peu les choses.

UNE

91
Adhara

Je suis actuellement en train de créer une application d'une seule page. Voici ce que j’ai jusqu’à présent qui, je crois, répondrait à votre question. J'ai un modèle de base (base.html) qui a un div avec la directive ng-view. Cette directive indique à angular où placer le nouveau contenu. Notez que je suis moi-même un novice de angularjs et que, par conséquent, je ne dis pas que c'est la meilleure façon de le faire.

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>
9
Austin
<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 a accès au menu div. Et widgetController ont accès aux deux.

6
Muhammad Awais

Nous pouvons simplement déclarer plusieurs contrôleurs dans le même module. Voici un exemple:

  <!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>
3
Abdallah Okasha

Je viens de mettre une simple déclaration de l'application

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

Ensuite, j'ai construit un service et deux contrôleurs

Pour chaque contrôleur, j'avais une ligne dans le JS

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

Et dans le HTML, j'ai déclaré la portée de l'application dans une div

<div ng-app="app">

et chaque contrôleur contrôlent séparément dans leur propre div entourant (au sein de l'application div)

<div ng-controller="EditableRowCtrl">

Cela a bien fonctionné

2
pat capozzi

Vous pourriez également avoir intégré toutes vos vues de modèle dans votre fichier html principal. Par exemple:

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

Ainsi, si chaque modèle nécessite un contrôleur différent, vous pouvez toujours utiliser le routeur angulaire. Voir ce dossier pour un exemple de travail http://plnkr.co/edit/9X0fT0Q9MlXtHVVQLhgr?p=preview

De cette façon, une fois que l'application est envoyée du serveur à votre client, elle est complètement autonome, en supposant qu'il ne nécessite aucune requête de données, etc.

0
Daimonos