Search code examples
angularjsangularjs-controller

Get parent controller in child controller which all use 'controller as vm' notation


Parent controller set to 'parentCtrl as vm' and chield set to 'childCtrl as vmc' to be no name conflict and it works well.

How can I get access to parent controller in child controller?

Note that '$scope.$parent' did not work.


Solution

  • To access the parent controller using the '$scope' notation just use '$scope.$parent'.

    However the 'controller as vm' notation lacked a detail that makes it work with some behavior:

    '$scope.$parent.vm'

    app.controller('childCtrl', [
        '$scope', function ($scope) {
            var vmc = this;
    
            // To protected access as vmc.parent
            Object.defineProperty(vmc, 'parent', {
                get: function () {
                    return $scope.$parent.vm;
                }
            });
        }
    ]);
    

    However changing the parent objects have side effects on primitive objects which may be understood in the following angular.js documentation.

    JavaScript Prototypal Inheritance

    Example:

    Working example on JS Bin

    <section class="parent" 
             data-ng-controller="parentCtrl as vm">
      <input data-ng-model="vm.name">
    
      <!-- have to change the prefix after the 'as' not to have conflict -->
      <section class="child"
               data-ng-controller="childCtrl as vmc">
        <input data-ng-model="vm.name">
        <!-- same results -->
        <input data-ng-model="$parent.vm.name">
        <!-- same results -->
        <input data-ng-model="vmc.parent.name">
        <!-- same results -->
        <button data-ng-click="vmc.changeName()">Change name</button>
      </section>
    </section>
    

    (function(){
      var app = angular.module('app', []);
      app.controller('parentCtrl', [
            '$scope', function ($scope) {
                var vm = this;
                vm.name = 'Julia';
            }
        ]);
      app.controller('childCtrl', [
            '$scope', function ($scope) {
                var vmc = this;
    
                // To protected access as vmc.parent
                Object.defineProperty(vmc, 'parent', {
                    get: function () {
                        return $scope.$parent.vm;
                    }
                });
              vmc.changeName = function(){
                vmc.parent.name = 'Other ' + vmc.parent.name;
              };
            }
        ]);
    })();