AngularJS:ng-include和ng-controller

时间:2014-11-23 10:02:25

标签: javascript angularjs angularjs-scope angularjs-ng-include

我有一个应用程序,我正在构建角度,我有大约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在视图范围下面添加了一个额外的范围层。 outout from console in attached example

额外点:如果我不能使用$ scope对象并且可以坚持var vm = this;这样做的方式,那将是更好的选择。但乞丐不能选择:)

app.controller('MainCtrl', function($scope) {
  var vm = this;

非常感谢你。

3 个答案:

答案 0 :(得分:31)

如果您将外部控制器的范围设为vm,将内部控制器设置为foo,则可以轻松将它们分开,并在内部控制器中引用vm。

Demo

<强> 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,以减少您的观点与控制器之间的混淆。

预期产出:

output showing the conditionally hidden\shown items

答案 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-includeng-show等)会生成自己的范围。

如果将来某人有意或无意地更改您的HTML并添加范围,您无法控制。

我建议使用驻留在MainCtrl上的函数,并通过继承范围来访问它们。

Plunker

$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());