Javascript AngularJS:ng-include 和 ng-controller
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/27087730/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
AngularJS : ng-include and ng-controller
提问by DShorty
I have an app which I am building with angular, I have about 8-10 views to build out. All the views have a shared footer, based on the view and a set of business rules i need to conditionally show / hide some of the content on the footer.
我有一个正在用 angular 构建的应用程序,我有大约 8-10 个视图要构建。所有视图都有一个共享页脚,基于视图和一组业务规则,我需要有条件地显示/隐藏页脚上的一些内容。
So. I have controllers for each view, and then one for the footer. I include the common footer layout using ng-include, where the html I am including references the footer controller in the ng-controller.
所以。我有每个视图的控制器,然后是页脚的控制器。我使用 ng-include 包含了常见的页脚布局,其中我包含的 html 引用了 ng-controller 中的页脚控制器。
Index.html
索引.html
<body ng-controller="MainCtrl as vm">
<p>Message from Main Controller '{{vm.mainMessage}}'</p>
<div ng-include="'commonFooter.html'"></div>
</body>
commonFooter.html
通用页脚.html
<div ng-controller="FooterCtrl as vm">
<p>Message from Footer Controller '{{vm.message}}'</p>
<p ng-show="vm.showSomthing">Conditional footer Content</p>
</div>
I want each views controller to determine the state of the footer and whether specific content is hidden or not. (shouldDisplaySomthingInFooter below)
我希望每个视图控制器确定页脚的状态以及特定内容是否隐藏。(shouldDisplaySomthingInFooter 下面)
app.controller('MainCtrl', function($scope) {
var vm = this;
vm.mainMessage= 'HEELO';
vm.shouldDisplaySomthingInFooter = true;
window.console.log('Main scope id: ' + $scope.$id);
});
Then i had intended that in the FooterController would reach back into the parent controller and pull out the specific settings to enable / disable content based on the business rules.
然后我打算在 FooterController 中返回到父控制器并拉出特定设置以根据业务规则启用/禁用内容。
app.controller('FooterCtrl', function($scope) {
var vm = this;
vm.message = 'vm footer';
window.console.log('Footer scope id: ' + $scope.$id);
window.console.log('Footer parent scope id: ' + $scope.$parent.$id);
window.console.log('Footer grandparent scope id: ' + $scope.$parent.$parent.$id);
window.console.log('Footer grandparent scope name: ' + $scope.$parent.$parent.mainMessage);
window.console.log('Footer grandparent scope condition: ' + $scope.$parent.$parent.shouldDisplaySomthingInFooter);
vm.showSomthing = false; //how to pull from parent scope to bind the ng-show to a value set in the parent from within a ng-include?
});
I have this example here: http://plnkr.co/edit/ucI5Cu4jjPgZNUitY2w0?p=preview
我在这里有这个例子:http: //plnkr.co/edit/ucI5Cu4jjPgZNUitY2w0?p=preview
What I am finding is that I when I reach into the parent scope to pull out the content it is coming back as undefined, and I am not sure why.
我发现的是,当我进入父范围以提取内容时,它以未定义的形式返回,我不知道为什么。
I can see that the scopes are nested to the grandparent level by checking the scopeid, I believe this is because the ng-include adds an extra scope layer below the view scopes.

我可以通过检查 scopeid 看到范围嵌套到祖父级别,我相信这是因为 ng-include 在视图范围下方添加了一个额外的范围层。

Extra points: If i can not have to use the $scope object and can stick with the var vm = this;way of doing it that would be preferable. But beggars cant be choosers :)
加分:如果我不必使用 $scope 对象并且可以坚持var vm = this;这样做的方式,那将是可取的。但乞丐不能挑剔:)
app.controller('MainCtrl', function($scope) {
var vm = this;
Thank you very much in advance.
非常感谢您提前。
回答by Kyle Muir
If you scope your outside controller as vmand your inside controller as foo, you can then separate them easily and refer to vm within the inside controller.
如果您将外部控制器范围设为vm并将内部控制器设为foo,那么您可以轻松地将它们分开并在内部控制器中引用 vm。
HTML:
HTML:
<body ng-controller="MainCtrl as vm">
<p>Message from Main Controller '{{vm.mainMessage}}'</p>
<div ng-include="'commonFooter.html'"></div>
</body>
CommonFooter.html:
CommonFooter.html:
<div ng-controller="FooterCtrl as footer">
<p>Message from Footer Controller '{{footer.message}}'</p>
<p ng-show="vm.shouldDisplaySomethingInFooter">Conditional footer Content</p>
</div>
app.js:
应用程序.js:
var app = angular.module('plunker', []);
app.controller('MainCtrl', function() {
var self = this;
self.mainMessage = 'Hello world';
self.shouldDisplaySomethingInFooter = true;
});
app.controller('FooterCtrl', function() {
var self = this;
self.message = 'vm footer';
});
Note: I renamed your var vm = thisto var self = thisfor clarity and to reduce confusion between your views and your controllers.
注:我改名你var vm = this要var self = this清楚和大家的意见和你的控制器之间减少混乱。
Expected output:
预期输出:


回答by hon2a
You've misunderstood what the controller assyntax (see documentation) is used for. It is just a way to expose a particular controller on your local scope, so that you can access its properties from a template. When you use someController as vmin both your parent and footer templates, you don't somehow create a connection between the controllers or anything like that. You're just setting a vmproperty on your footer's scope, so when you use it in your footer template, you're accessing the footer's controller (and you've blocked your way to the parent controller).
您误解了控制器作为语法(请参阅文档)的用途。这只是在本地范围内公开特定控制器的一种方式,以便您可以从模板访问其属性。当您someController as vm在父模板和页脚模板中使用时,您不会以某种方式在控制器或类似的东西之间创建连接。您只是vm在页脚的范围内设置了一个属性,因此当您在页脚模板中使用它时,您正在访问页脚的控制器(并且您已经阻止了通往父控制器的路)。
For what you're trying to do, you basically don't need the controller assyntax at all. Just properly put your data on $scopeand let the scope hierarchy do the rest for you.
对于您想要做的事情,您基本上根本不需要控制器作为语法。只需正确放置您的数据$scope,让范围层次结构为您完成剩下的工作。
In your parent controller:
在您的父控制器中:
$scope.features.rock = true;
$scope.features.roll = false;
In your footer template
在您的页脚模板中
<p ng-show="features.rock">...</p>
<p ng-show="features.roll">...</p>
You can now also see and change the featuresfrom your other controllers (as their scopes are descendants of parent controller's scope).
您现在还可以features从其他控制器中查看和更改(因为它们的范围是父控制器范围的后代)。
回答by Omri Aharon
I fiddled around with your plunker, but also changed var vm = this;to $scope, so I'm failing at extra points :-)
我摆弄了你的 plunker,但也改成var vm = this;了$scope,所以我在加分上失败了 :-)
I would strongly advise against the usage of $scope.$parentexactly for the reason you show. Various directives such as ng-include, ng-showetc, generate their own scopes.
我强烈建议不要$scope.$parent完全出于您展示的原因使用。各种指令,如ng-include,ng-show等,生成自己的范围。
You have no control if someone in the future changes your html and adds scopes, intentionally or otherwise.
您无法控制将来是否有人有意或无意地更改您的 html 并添加范围。
I recommend using functions that reside on your MainCtrland accessing them via inheriting scopes.
我建议使用驻留在您的函数MainCtrl并通过继承范围访问它们。
$scope.getShouldShow = function() {
return $scope.shouldDisplaySomthingInFooter;
};
$scope.setShouldShow = function(val) {
$scope.shouldDisplaySomthingInFooter = val;
};
$scope.getMainMessage = function () {
return $scope.mainMessage;
}
And calling them:
并打电话给他们:
<p ng-show="getShouldShow();">Conditional footer Content</p>
And:
和:
window.console.log('Footer grandparent scope name: ' + $scope.getMainMessage());
window.console.log('Footer grandparent scope condition: ' + $scope.getShouldShow());

