Несколько контроллеров с функцией AngularJS в одностраничном приложении

Я хочу знать, как использовать несколько контроллеров для одностраничного приложения. Я попытался понять это, и я нашел вопросы, очень похожие на мои, но есть только тонна различных ответов, решая конкретную проблему, в результате которой вы не используете несколько контроллеров для одностраничного приложения.

Это потому, что было бы нецелесообразно использовать несколько контроллеров для одной страницы? Или это просто невозможно?

Скажем, у меня уже есть контрольный карусель с изображением пинка, работающий на главной странице, но потом я узнаю, как (допустим) использовать модалы, и мне нужен новый контроллер для этого (или любая другая вещь, в которой я нуждаюсь контроллер). Что я буду делать?

Я видел некоторые ответы на другие вопросы, на которых они спрашивают почти то же самое, что и я, и люди отвечают "* OMG. Почему бы вам даже сделать это, просто сделайте это...".

Каков наилучший способ, или как вы это делаете?

Edit

Многие из вас отвечают, чтобы просто объявить два контроллера, а затем использовать ng-controller для его вызова. Я использую этот бит кода ниже, а затем вызываю MainCtrl с ng-контроллером.

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

Почему мне даже нужно установить контроллер здесь, если я могу просто использовать ng-controller без него? Вот что меня смутило. (и вы не можете добавить два контроллера таким образом, я думаю...)

Ответ 1

В чем проблема? Чтобы использовать несколько контроллеров, просто используйте несколько директив ngController:

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

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

Вам нужно будет иметь контроллеры, доступные в вашем прикладном модуле, как обычно.

Самый простой способ сделать это можно так же просто, как объявить функции контроллера следующим образом:

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

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

Ответ 2

Я думаю, что вам не хватает значения "одностраничное приложение".

Это не значит, что вы физически будете иметь один .html, вместо этого у вас будет один основной index.html и несколько файлов NESTED.html. Итак, почему одностраничное приложение? Потому что таким образом вы не загружаете страницы стандартным способом (т.е. Браузерный вызов, который полностью обновляет полную страницу), но вы просто загружаете часть контента с помощью Angular/Ajax. Поскольку вы не видите мерцание между изменениями страницы, создается впечатление, что вы не переместились со страницы. Таким образом, вы чувствуете, что находитесь на одной странице.

Теперь я предполагаю, что вы хотите иметь МНОЖЕСТВЕННОЕ содержимое для вашего приложения SINGLE PAGE: (например, домой, контакты, портфолио и магазин. Ваше одностраничное/многостраничное приложение (способ angular) будет организовано следующим образом:

  • index.html: содержит заголовок, <ng-view> и нижний колонтитул
  • contacts.html: содержит форму контакта (без заголовка, без нижнего колонтитула)
  • portfolio.html: содержит данные портфеля (без верхнего колонтитула)
  • store.html: содержит хранилище, без верхнего колонтитула.

Вы находитесь в индексе, вы нажимаете на меню под названием "контакты" и что происходит? angular заменяет тег <ng-view> кодом contacts.html

Как вы это достигаете? с ngRoute, как вы это делаете, у вас будет что-то вроде:

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

Это вызовет правильный html, передающий ему правый контроллер (обратите внимание: не указывать директиву ng-controller в contacts.html, если вы используете маршруты)

Тогда, конечно, вы можете объявить столько директив ng-controller внутри вашей страницы contactss.html. Это будут дочерние контроллеры ContactCtrl (таким образом, наследуя от него). Но для одного маршрута, внутри routeProvider, вы можете объявить один контроллер, который будет действовать как "Контроллер отца частичного представления".

ИЗМЕНИТЬ Представьте себе следующие шаблоны /contacts.html

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

вышеуказанный routeProvider будет вводить контроллер в ваш содержащий div. В основном вышеописанный html automaticaly становится:

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

Когда я говорю, что у вас могут быть другие контроллеры, вы можете подключить контроллеры к внутренним элементам DOM, как показано ниже:

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

Надеюсь, это немного изменит ситуацию.

А

Ответ 3

В настоящее время я создаю одностраничное приложение. Вот что я имею до сих пор, что, по моему мнению, будет отвечать на ваш вопрос. У меня есть базовый шаблон (base.html), в котором есть div с директивой ng-view. Эта директива сообщает angular, куда помещать новое содержимое. Заметьте, что я новичок в angularjs, поэтому я никоим образом не говорю, что это лучший способ сделать это.

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>

Ответ 4

<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 имеет доступ к меню div. И widgetController имеют доступ к обоим.

Ответ 5

Я просто поместил одно простое объявление приложения

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

Затем я построил одну службу и два контроллера

Для каждого контроллера у меня была строка в JS

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

И в HTML я объявил область приложения в окружении div

<div ng-app="app">

и каждая область контроллера отдельно в своем собственном окружении div (в приложении div)

<div ng-controller="EditableRowCtrl">

Это отлично работает

Ответ 6

Мы можем просто объявить более одного контроллера в том же модуле. Вот пример:

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

Ответ 7

Вы также можете включить все ваши шаблоны в свой основной файл html. Например:

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

Таким образом, если для каждого шаблона требуется другой контроллер, вы все равно можете использовать angular -router. См. Этот плунж для рабочего примера http://plnkr.co/edit/9X0fT0Q9MlXtHVVQLhgr?p=preview

Таким образом, как только приложение будет отправлено с сервера на ваш клиент, оно полностью самодостаточно, предполагая, что ему не нужно делать какие-либо запросы данных и т.д.