在单页应用程序中使用 AngularJS 的多个控制器

我想知道的是如何使用单页应用程序的多个控制器。我试图弄清楚它,我发现问题非常类似于我的,但只是有一吨不同的答案解决一个特定的问题,你最终没有使用多个控制器为一个单一的页面应用程序。

是不是因为对一个页面使用多个控制器不明智?还是根本不可能?

假设我已经在主页上使用了一个非常棒的图像旋转木马控制器,但是之后我学会了如何(假设)使用 Modals,并且我还需要一个新的控制器(或者其他任何我需要控制器的东西)。那我该怎么办?

我已经看到了一些对其他问题的回答,他们问了几乎和我一样的问题,人们回答“ * OMG。你为什么要这么做,就这么做...”。

最好的方法是什么,或者你是怎么做到的?

剪辑

你们中的许多人只是回答声明两个控制器,然后使用 n- 控制器来调用它。 我使用下面这段代码,然后使用 ng-controller 调用 MainCtrl。

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

如果我可以只使用 n- 控制器而不使用它,为什么还需要在这里设置控制器呢?这就是让我困惑的地方。(我认为你不能这样添加两个控制器...)

247581 次浏览

What is the problem? To use multiple controllers, just use multiple ngController directives:

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


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

You will need to have the controllers available in your application module, as usual.

The most basic way to do it could be as simple as declaring the controller functions like this:

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


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

I'm currently in the process of building a single page application. Here is what I have thus far that I believe would be answering your question. I have a base template (base.html) that has a div with the ng-view directive in it. This directive tells angular where to put the new content in. Note that I'm new to angularjs myself so I by no means am saying this is the best way to do it.

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>

I think you are missing the "single page app" meaning.

That doesn't mean you will physically have one .html, instead you will have one main index.html and several NESTED .html file. So why single page app? Because this way you do not load pages the standard way (i.e. browser call that completely refreshes the full page) but you just load the content part using Angular/Ajax. Since you do not see the flickering between page changes, you have the impression that you didn't move from the page. Thus, you feel like you are staying on a single page.

Now, I'm assuming that you want to have MULTIPLE contents for your SINGLE PAGE app: (e.g.) home, contacts, portfolio and store. Your single page/multiple content app (the angular way) will be organized this way:

  • index.html: contains header, <ng-view> and footer
  • contacts.html:contains the contact form (no header, no footer)
  • portfolio.html:contains the portfolio data (no header no footer)
  • store.html: contains the store, no header no footer.

You are in index, you click on the menu called "contacts" and what happens? Angular replaces the <ng-view> tag with the contacts.html code

How do you achieve that? with ngRoute, as you are doing, you will have something like:

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

This will call the right html passing the right controller to it (please note: do not specify ABC0 directive in contacts.html if you are using routes)

Then, of course, you can declare as many ng-controller directives inside your contacts.html page. Those will be child controllers of ContactCtrl (thus inheriting from it). But for a single route, inside the routeProvider, you can declare a single Controller that will act as the "Father controller of the partial view".

EDIT Imagine the following templates/contacts.html

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

the above routeProvider will inject a controller into your containing div. Basically the above html automaticaly becomes:

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

When I say you can have others controllers, means that you can plug controllers to inner DOM elements, as the following:

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

I hope this clarify things a bit.

A

I just put one simple declaration of the app

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

Then I built one service and two controllers

For each controller I had a line in the JS

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

And in the HTML I declared the app scope in a surrounding div

<div ng-app="app">

and each controller scope separately in their own surrounding div (within the app div)

<div ng-controller="EditableRowCtrl">

This worked fine

You could also have embed all of your template views into your main html file. For Example:

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

This way if each template requires a different controller then you can still use the angular-router. See this plunk for a working example http://plnkr.co/edit/9X0fT0Q9MlXtHVVQLhgr?p=preview

This way once the application is sent from the server to your client, it is completely self contained assuming that it doesn't need to make any data requests, etc.

<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 have access for menu div. And widgetController have access to both.

We can simply declare more than one Controller in the same module. Here's an example:

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