Search code examples
javascriptangularjsangularjs-scopeangularjs-ng-include

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. 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. outout from console in attached example

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.


Solution

  • 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:

    output showing the conditionally hidden\shown items