Кілька контролерів з AngularJS в додатку на одній сторінці


102

Хочу знати, як використовувати кілька контролерів для однієї сторінки програми. Я спробував це розібратися, і я знайшов питання, схожі на мої, але є лише маса різних відповідей, що вирішують конкретну проблему, коли ви не використовуєте декілька контролерів для однієї сторінки програми.

Це тому, що не було б розумно використовувати кілька контролерів для однієї сторінки? Або це просто неможливо?

Скажімо, у мене вже є головна сторінка, що працює на головній сторінці контролера каруселей зображення, але потім я дізнаюся, як (скажімо) використовувати модалі, і для цього мені потрібен новий контролер (або будь-яка інша річ, яка мені потрібна контролеру). Що я тоді робитиму?

Я бачив деякі відповіді на інші запитання, де вони задають майже ті ж речі, що і я, а люди відповідають "* OMG. Чому б ти це робив, просто роби це ...".

Який найкращий спосіб, або як це зробити?

Редагувати

Багато з вас відповідають лише оголосити два контролери, а потім використовувати ng-контролер, щоб викликати це. Я використовую цей біт коду нижче, а потім викликаю MainCtrl з ng-контролером.

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

Чому мені взагалі потрібно встановити контролер, якщо я можу просто використовувати ng-контролер без нього? Це мене бентежило. (і ви не можете додати два контролери таким чином, я думаю ...)


Я не думаю, що я можу оголосити 2 контролера для одного файлу .html? як це робиться? when: /home, controller: MainCtrl. Ви не можете додати більше цього, або ви маєте на увазі просто викликати його за допомогою ng-контролера?

3
@Mosho, ти робиш крок 1, крок 2, але не пояснює, як і чому. Якщо це так просто, то поясніть, будь ласка, як. Це як сказати використовувати AngularJS, Готово. Ви можете розробити / пояснити? Або як це з червня, вони можуть не відповісти, може хтось інший пояснить?
redfox05

Відповіді:


96

В чому проблема? Щоб використовувати декілька контролерів, просто використовуйте декілька директив 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
Це, як це робиться? Я використовую цеwhen /home, controller: MainCtrl

8
Якщо ви виходите з прикладів, які ставлять "ng-додаток" у кожному DIV поруч із вашим "ng-контролером", спробуйте перемістити лише один "ng-додаток" у тег "body" (та видаліть per-div " ng-app "теги", якщо працює лише ваш перший контролер. (Я пам’ятаю це з моїх кутових днів новачків.)
ftexperts

1
Єдине питання, з яким я мав використовуватись ng-controllerу кількох елементах DOM, - це сказати у сценарії, коли у мене є багато елементів, які друкуються на DOM через ng-repeat. Скажімо, кожен із них робить дзвінок до ng-controller="myController. З деяких журналів консолей, які я бачив у своїй програмі, myControllerповторно ініціалізується, коли елемент EACH видається у DOM, який викликає його .... питання, але цікаво, чи інші взагалі пережили це ....
twknab

91

Я думаю, вам не вистачає значення "додаток для однієї сторінки".

Це не означає, що ви фізично матимете один .html, натомість у вас буде один головний index.htmlта кілька файлів NESTED .html. То чому ж додаток для однієї сторінки? Тому що ви не завантажуєте сторінки стандартним способом (тобто виклик браузера, який повністю оновлює повну сторінку), але ви просто завантажуєте частину вмісту за допомогою Angular / Ajax. Оскільки ви не бачите мерехтіння між змінами сторінки, у вас складається враження, що ви не перейшли зі сторінки. Таким чином, ви відчуваєте, що перебуваєте на одній сторінці.

Тепер я припускаю, що ви хочете мати ВІДМІЛЬНИЙ вміст для додатка SINGLE PAGE: (наприклад, дома, контакти, портфоліо та магазин). Ваша додаткова сторінка / кілька додатків для вмісту (кутовий спосіб) буде організована таким чином:

  • index.html: містить заголовок <ng-view>та колонтитул
  • contacts.html: містить контактну форму (без заголовка, без колонтитулу)
  • portfolio.html: містить дані портфоліо (без заголовка, колонтитула)
  • store.html: містить магазин, немає заголовка, колонтитула.

Ви в індексі, натискаєте на меню під назвою "контакти" і що відбувається? Кутовий замінює <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-контролерів на своїй сторінці contact.html. Це будуть дочірні контролери ContactCtrl(таким чином успадковуючи це). Але для одного маршруту, всередині routeProvider, ви можете оголосити єдиний контролер, який буде виконувати роль "контролера батька часткового перегляду".

EDIT Уявіть наступні шаблони / Contacts.html

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

вище routeProviderбуде введено контролер у ваш div, що містить. В основному, вище html автоматично стає:

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

Я сподіваюся, що це трохи прояснить речі.

А


Отже, якщо ви оголосили, наприклад, <div ng-controller="FancyStuffController">всередині тегу body, який вже встановлений контролер, наприклад, <body ng-controller="BodyController">це буде працювати? я отримую помилки про те, $apply already in progressколи я це роблю, але я думаю, що це пов'язано з dpd.js. Не вникати в це, я думаю, що його просто завантажують у два рази чи щось, не впевнений, як, але моє використання контролера, можливо, намагається перезавантажити це.
блам

1
@BrianThomas Звичайно, це має працювати. Будьте уважні: якщо ви хочете вставити контролер у вигляд, використовуйте $ routeProvider, не пишіть ng-контролер у тег div.
Адхара

9

Зараз я перебуваю в процесі створення програми на одній сторінці. Ось що я досі мав, на мою думку, відповів би на ваше запитання. У мене є базовий шаблон (base.html), який містить в собі div з ng-viewдирективою. Ця директива вказує кутовий, куди слід помістити новий вміст. Зверніть увагу, що я сам новачок у 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>

Дійсно, я також використовую ng-view, щоб я міг використовувати main.html у своєму index.html. але у вас є / home та / about, і два контролери є для кожного. У мене є тільки index.html з ng-view до мого main.html. Я не можу встановити два контролери для main.html, як ви це зробилиwhen /home

Подивіться першу відповідь з цього поста: stackoverflow.com/questions/17354568/…
Остін

добре, я знаю, як встановити більше when. Я хочу два контролери для одного шаблону. Або мабі я неправильно зрозумів, що ти намагався мені сказати?

Замість використання контролерів спробуйте використовувати директиви. Ви можете використовувати багато директив для одного шаблону. Якщо ви все ще хочете використовувати свої контролери, ось відео про те, як директиви можуть зв’язуватися з контролерами: egghead.io/lessons/angularjs-directives-talking-to-controllers
Остін

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 має доступ до меню div. І віджетController має доступ до обох.


Це здається просто, але не має жодних відгуків. Це найкраща практика чи погана?
redfox05

1
що ви будете робити, якщо у вас багато сторінок 100+ контролерів! ... неоднозначна практика.
АріфМустафа

3

Ми можемо просто оголосити більше одного контролера в одному модулі. Ось приклад:

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

Я просто поставив одну просту заяву програми

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

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

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

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

І в HTML я оголосив область застосування в навколишньому діві

<div ng-app="app">

і кожен контролер охоплює окремо у своєму оточуючому div (у програмі div)

<div ng-controller="EditableRowCtrl">

Це спрацювало чудово


0

Ви також могли вставити всі перегляди шаблонів у свій головний 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>

Таким чином, якщо для кожного шаблону потрібен інший контролер, ви все одно можете використовувати кутовий маршрутизатор. Дивіться цей планк для робочого прикладу http://plnkr.co/edit/9X0fT0Q9MlXtHVVQLhgr?p=preview

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

Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.