The goal here is to have two different directives that are technically siblings share functionality. I will either use one or the other, never one inside the other.
However, the second directive will have all the capability of the first with some small additions. Because of this, I would like the functionality to inherit from the "Parent" directive to the "Child".
I'm achieving this by re-using the same directive definition object from the Parent on the Child, with the exception of the controller/template fields being changed.
This was all working well up until I hit the watchers from my ParentDirCtrl
. For some reason the watcher seems to be set up correctly watching mydir.obj1
and yet somehow inside the watcher callback function mydir.obj1
becomes undefined.
I'm assuming something about _.extend
/$controller
is changing how the $scope
s work so mydir.obj1
isn't defined in the ParentDirCtrl
, but I'm not sure why that would be the case.
angular.module('plunker', [])
// lodash
.constant('_', _)
.controller('MainCtrl', function($scope, $timeout) {
$scope.obj = {
name: 'John',
age: 30,
};
})
.controller('ParentDirCtrl', function($scope) {
var mydir = this;
mydir.doStuffInParent = function() {
alert('executed from the parent directive');
}
$scope.$watch('mydir.obj1', function() {
// ====================================
// ERROR
// Why is 'mydir.obj1' undefined when
// occupation is set?
// ====================================
mydir.obj1.occupation = 'Meteorologist';
});
})
.directive('parentDirective', parentDirective)
.directive('childDirective', function() {
// borrow the directive definition object from the parent directive
var parentDDO = parentDirective();
// uodate the template and controller for our new directive
parentDDO.template = [
'<div>',
'<p ng-click="mydir.doStuffInParent()">{{mydir.obj1.name}}</p>',
'<p ng-click="mydir.doStuffInChild()">{{mydir.obj1.age}}</p>',
'</div>'
].join('');
parentDDO.controller = function($scope, $controller, _) {
// extend 'this' with the Parent's controller
var mydir = _.extend(this, $controller('ParentDirCtrl', { $scope: $scope }));
mydir.doStuffInChild = function() {
alert("executed from the child directive");
};
};
return parentDDO;
});
// this will be moved to the top during declaration hoisting
function parentDirective() {
return {
restrict:'E',
scope: {},
bindToController: {
obj1: '=',
},
template: '<div>{{mydir.obj1}}</div>',
controller: 'ParentDirCtrl',
controllerAs: 'mydir',
};
}
obj1
is populated on the child controller instance - that's why mydir.obj1
is undefined in the parent watcher. You can access obj1
directly via scope or by using the reference passed into the watcher:
$scope.$watch('mydir.obj1', function(val) {
$scope.mydir.obj1.occupation = 'Meteorologist';
// or
val.occupation = 'Meteorologis';
});
There is no scope inheritance here - both controllers operate on the same scope. Controller-AS syntax is what confuses you - I'd get rid of it to make things clearer.