Spencer
Spencer

Reputation: 382

Child controller not inheriting from parent controller

I've been having a lot of trouble with understanding scope inheritance and I've tried my best to pass data objects from a parent controller into the child controller, but I can't seem to get things to work. Can someone explain why this isn't functioning? Thank you!

EDIT: I didn't specify this earlier, but it's a project requirement to use the John Papa style guide, so I can't solve this problem by using $scope in either of the controllers.

UPDATE: It seems I misunderstood the purpose of using this... based on help from posters below, I now understand that certain actions require the use of $scope and John Papa's style guide simply asks developers to use this when appropriate to avoid scope conflicts, not as a replacement for scope

JS

//parent.controller.js
(function () {
    'use strict';

    angular
        .module('app')
        .controller('ParentController', ParentController);

    ParentController.$inject = ['$scope'];

    function ParentController($scope) {
        var vm = this;
        console.log(this);
        vm.test = {};
        vm.test.label = "This is being set in the parent controller.";
    }
})();

//child.controller.js
(function () {
    'use strict';

    angular
        .module('app')
        .controller('ChildController', ChildController);

    ChildController.$inject = ['$scope'];

    function ChildController($scope) {
        var vm = this;
        vm.test = vm.test;
    }
})();

HTML

<div ng-controller="ParentController as vm">
     <div>PARENT: {{vm.test.label}}</div>
     <div ng-controller="ChildController as vm">
          <div>CHILD: {{vm.test.label}}</div>
     </div>
</div>

RESULT

PARENT: 'This is being set in the parent controller.'
CHILD:

Upvotes: 0

Views: 387

Answers (2)

random
random

Reputation: 7891

After checking the plnkr,hope I was able to understand your question, and giving answer based on it:

In controller file, for ChildController

var childCtrl = this;

// Why don't either of these work?
// childCtrl.test = parentCtrl.test;
// childCtrl.test = this.parentCtrl.test;
  • assigning parentCtrl.test, doesn't makes any sense, as it is the object of the parent controller.
  • this.parentCtrl.test will get evaluated to childCtrl.parentCtrl.test which is invalid.

Following worked because-

// But this does...
childCtrl.test = $scope.parentCtrl.test;

During the code execution

  • Two separate scopes will get created each for ParentController and ChildController.

  • child will inherit the properties of parent, those which are not present in childController and will be assigned to the childController scope. Due to which you where able to access value in child with scope.

Upvotes: 1

Suneet Bansal
Suneet Bansal

Reputation: 2702

Issue is: vm is also the part of the $scope itself. So you can not have same this instance for Parent & Child controller. Otherwise you will be facing issues while using them. If you want to isolate this instance for Parent & Child then give different names. Since vm is also the part of the controller so if you want to access Parent's vm inside Child controller then you will have to do $scope.vm

Working code as per your requirement is attached below:

Controller
---------
(function () {
                'use strict';

    angular
        .module('app', [])
        .controller('ParentController', ParentController);

    ParentController.$inject = ['$scope'];

    function ParentController($scope) {
        var vm = this;
        console.log(this);
        vm.test = {};
        vm.test.label = "This is being set in the parent controller.";
    }
})();

(function () {
    'use strict';

    angular
        .module('app')
        .controller('ChildController', ChildController);

    ChildController.$inject = ['$scope'];

    function ChildController($scope) {
        var childVm = this;
        childVm.test = $scope.vm.test;
    }
})();


HTML
---

<div ng-app="app">
            <div ng-controller="ParentController as vm">
                <div>PARENT: {{vm.test.label}}</div>
                <div ng-controller="ChildController as childVm">
                    <div>CHILD: {{childVm.test.label}}</div>
                </div>
            </div>
        </div>

Cheers!

Upvotes: 3

Related Questions