我有一个应用程序,我正在构建角度,我有大约8-10个视图来构建。 所有视图都有一个共享的页脚,基于视图和一组业务规则,我需要有条件地显示/隐藏页脚上的一些内容。
因此。 我有每个视图的控制器,然后一个页脚。 我使用ng-include包含公共页脚布局,其中我包含的html引用了ng-controller中的页脚控制器。
的index.html
<body ng-controller="MainCtrl as vm">
<p>Message from Main Controller '{{vm.mainMessage}}'</p>
<div ng-include="'commonFooter.html'"></div>
</body>
commonFooter.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>
我希望每个视图控制器确定页脚的状态以及是否隐藏特定内容。 (shouldDisplaySomthingInFooter)
app.controller('MainCtrl', function($scope) {
var vm = this;
vm.mainMessage= 'HEELO';
vm.shouldDisplaySomthingInFooter = true;
window.console.log('Main scope id: ' + $scope.$id);
});
然后我原本打算在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?
});
我在这里有这个例子: http://plnkr.co/edit/ucI5Cu4jjPgZNUitY2w0?p=preview
我发现的是,当我进入父作用域以取出它作为未定义的内容时,我不知道为什么。
我可以通过检查scopeid来看到范围嵌套到祖父级别,我相信这是因为ng-include在视图范围下面添加了一个额外的范围层。
额外点:如果我不能使用$ scope对象并且可以坚持var vm = this;
这样做的方式,那将是更好的选择。但乞丐不能选择:)
app.controller('MainCtrl', function($scope) {
var vm = this;
非常感谢你。
答案 0 :(得分:31)
如果您将外部控制器的范围设为vm
,将内部控制器设置为foo
,则可以轻松将它们分开,并在内部控制器中引用vm。
<强> HTML 强>:
<body ng-controller="MainCtrl as vm">
<p>Message from Main Controller '{{vm.mainMessage}}'</p>
<div ng-include="'commonFooter.html'"></div>
</body>
<强> 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 强>:
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';
});
注意:为了清晰起见,我将var vm = this
重命名为var self = this
,以减少您的观点与控制器之间的混淆。
预期产出:
答案 1 :(得分:3)
您误解了控制器语法(see documentation)的用途。它只是一种在本地作用域上公开特定控制器的方法,以便您可以从模板访问其属性。当您在父模板和页脚模板中使用someController as vm
时,您不会以某种方式在控制器之间创建连接或类似的东西。您只是在页脚范围内设置vm
属性,因此当您在页脚模板中使用它时,您将访问页脚控制器(并且您&# 39;我们阻止了你到父控制器的方式。)
对于您尝试做的事情,您基本上根本不需要控制器作为语法。只需将您的数据正确放在$scope
上,然后让范围层次为您完成剩下的工作。
在您的父控制器中:
$scope.features.rock = true;
$scope.features.roll = false;
在页脚模板中
<p ng-show="features.rock">...</p>
<p ng-show="features.roll">...</p>
您现在还可以从其他控制器中查看和更改features
(因为它们的范围是父控制器范围的后代)。
答案 2 :(得分:2)
我摆弄了你的掠夺者,但也将var vm = this;
改为$scope
,所以我没有加分: - )
我强烈建议您不要使用$scope.$parent
,因为您显示的原因。各种指令(如ng-include
,ng-show
等)会生成自己的范围。
如果将来某人有意或无意地更改您的HTML并添加范围,您无法控制。
我建议使用驻留在MainCtrl
上的函数,并通过继承范围来访问它们。
$scope.getShouldShow = function() {
return $scope.shouldDisplaySomthingInFooter;
};
$scope.setShouldShow = function(val) {
$scope.shouldDisplaySomthingInFooter = val;
};
$scope.getMainMessage = function () {
return $scope.mainMessage;
}
并打电话给他们:
<p ng-show="getShouldShow();">Conditional footer Content</p>
和
window.console.log('Footer grandparent scope name: ' + $scope.getMainMessage());
window.console.log('Footer grandparent scope condition: ' + $scope.getShouldShow());