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.
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.
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>
I want each views controller to determine the state of the footer and whether specific content is hidden or not. (shouldDisplaySomthingInFooter below)
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.
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
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.
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 :)
app.controller('MainCtrl', function($scope) { var vm = this;
Thank you very much in advance.
AngularJS ng-include Directive The ng-include directive includes HTML from an external file. The included content will be included as childnodes of the specified element. The value of the ng-include attribute can also be an expression, returning a filename.
AngularJS ng-controller Directive The ng-controller directive adds a controller to your application. In the controller you can write code, and make functions and variables, which will be parts of an object, available inside the current HTML element. In AngularJS this object is called a scope.
templateUrl can also be a function which returns the URL of an HTML template to be loaded and used for the directive. AngularJS will call the templateUrl function with two parameters: the element that the directive was called on, and an attr object associated with that element.
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.
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'; });
Note: I renamed your var vm = this
to var self = this
for clarity and to reduce confusion between your views and your controllers.
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. 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).
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.
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).
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With