简体   繁体   English

AngularJS:ng-include和ng-controller

[英]AngularJS : ng-include and ng-controller

I have an app which I am building with angular, I have about 8-10 views to build out. 我有一个应用程序,我正在构建角度,我有大约8-10个视图来构建。 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. 所有视图都有一个共享的页脚,基于视图和一组业务规则,我需要有条件地显示/隐藏页脚上的一些内容。

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

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; 额外点:如果我不能使用$ scope对象并且可以坚持使用var vm = this; way of doing it that would be preferable. 这样做的方式更可取。 But beggars cant be choosers :) 但是乞丐不能选择:)

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

Thank you very much in advance. 非常感谢你提前。

If you scope your outside controller as vm and your inside controller as foo , you can then separate them easily and refer to vm within the inside controller. 如果将外部控制器作为vm并将内部控制器作为foo ,则可以轻松地将它们分开并引用内部控制器中的vm。

Demo 演示

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

Note: I renamed your var vm = this to var self = this for clarity and to reduce confusion between your views and your controllers. 注意:为了清楚起见,我将var vm = this重命名为var self = this ,以减少视图与控制器之间的混淆。

Expected output: 预期产量:

输出显示有条件隐藏\\显示的项目

You've misunderstood what the controller as syntax ( 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 vm in both your parent and footer templates, you don't somehow create a connection between the controllers or anything like that. 当您在父模板和页脚模板中使用someController as vm时,您不会以某种方式在控制器之间创建连接或类似的东西。 You're just setting a vm property 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). 您只是在页脚范围内设置vm属性,因此当您在页脚模板中使用它时,您正在访问页脚的控制器(并且您已阻止前往父控制器的方式)。

For what you're trying to do, you basically don't need the controller as syntax at all. 对于您要做的事情,您基本上根本不需要控制器作为语法。 Just properly put your data on $scope and 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 features from your other controllers (as their scopes are descendants of parent controller's scope). 您现在还可以查看和更改其他控制器的features (因为它们的范围是父控制器范围的后代)。

I fiddled around with your plunker, but also changed var vm = this; 我摆弄你的羽毛球,但也改变了var vm = this; to $scope , so I'm failing at extra points :-) $scope ,所以我没有加分:-)

I would strongly advise against the usage of $scope.$parent exactly for the reason you show. 我强烈建议不要使用$scope.$parent ,因为你显示的原因。 Various directives such as ng-include , ng-show etc, generate their own scopes. 诸如ng-includeng-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 MainCtrl and accessing them via inheriting scopes. 我建议使用驻留在MainCtrl上的函数,并通过继承范围访问它们。

Plunker Plunker

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

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM