【问题标题】:AngularJS : ng-include and ng-controllerAngularJS:ng-include 和 ng-controller
【发布时间】:2015-01-21 03:43:51
【问题描述】:

我有一个使用 Angular 构建的应用程序,我有大约 8-10 个视图要构建。 所有视图都有一个共享的页脚,基于视图和一组业务规则,我需要有条件地显示/隐藏页脚上的一些内容。

所以。 我有每个视图的控制器,然后是页脚的控制器。 我使用 ng-include 包含常见的页脚布局,其中我包含的 html 引用了 ng-controller 中的页脚控制器。

索引.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>

我希望每个视图控制器确定页脚的状态以及特定内容是否隐藏。 (应在下方显示SomthingInFooter)

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;

非常感谢您。

【问题讨论】:

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


    【解决方案1】:

    如果您将外部控制器的范围设置为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

    预期输出:

    【讨论】:

      【解决方案2】:

      您误解了 controller as 语法 (see documentation) 的用途。这只是一种在本地范围内公开特定控制器的方法,以便您可以从模板访问其属性。当您在父模板和页脚模板中使用someController as vm 时,您不会以某种方式在控制器或类似的东西之间创建连接。您只是在页脚的范围内设置 vm 属性,因此当您在页脚模板中使用它时,您正在访问页脚的控制器(并且您已经阻止了访问父控制器的方式)。

      对于您要执行的操作,您基本上根本不需要 controller as 语法。只需将您的数据正确地放在 $scope 上,然后让作用域层次结构为您完成其余的工作。

      在您的父控制器中:

      $scope.features.rock = true;
      $scope.features.roll = false;
      

      在您的页脚模板中

      <p ng-show="features.rock">...</p>
      <p ng-show="features.roll">...</p>
      

      您现在还可以从其他控制器中查看和更改features(因为它们的作用域是父控制器作用域的后代)。

      【讨论】:

        【解决方案3】:

        我摆弄了你的 plunker,但也将 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());
        

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 2016-09-04
          • 1970-01-01
          • 2018-03-27
          • 2014-02-17
          • 1970-01-01
          • 2017-02-02
          • 1970-01-01
          • 1970-01-01
          相关资源
          最近更新 更多