Reputation: 1408
I have a controller called main which has two nested directives called formDirective and dataDirective.
I have the following form in my formDirective view.
<form name="menuForm">
<h4>What is your name</h4>
<input name="name" ng-value="" ng-model="name">
</form>
I am trying to use $scope.watch to update some data in dataDirective when a form value is changed in formDirective.
When I put the following code inside my formDirective controller it works fine.
$scope.$watch('[menuForm.name.$viewValue]', function () {
console.log('name changed');
//update data directive here
}, true);
However this won't work for my solution because I need this code inside my parent controller as the directives need to communicate with each other and doing it this way would cause encapsulation issues.
When I put the following watcher inside my main controller it doesn't work - where I would expect it too. (I can browse it fine from web inspector).
$scope.$watch('[$scope.menuForm.name.$viewValue]', function () {
console.log('name changed');
//update data directive here
}, true);
Is anybody able to tell me how I can watch my formDirectives variable from my main controller?
Upvotes: 0
Views: 1782
Reputation: 15647
Is anybody able to tell me how I can watch my formDirectives variable from my main controller?
You can create directive with isolated scope and set up bi-directional binding between a local scope property and the parent scope property.
Example:
var app = angular.module("app",[])
.controller("mainctrl", function($scope) {
$scope.name = "";
})
.directive("myFormDirective", function() {
return {
restrict: 'E',
scope: {
model: '=myModel'
},
template: '<form name="menuForm"><h4>What is your name (Form Directive)</h4>' +
'<input name="name" ng-model="model"></form><p>',
link: function(scope, element, attrs) {}
};
})
.directive("myDataDirective", function() {
return {
restrict: 'E',
scope: {
model: '=myModel'
},
template: '<p>Data Directive: {{model}}</p>',
link: function(scope, element, attrs) {}
};
});
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.2.23/angular.min.js"></script>
<div ng-app="app" ng-controller="mainctrl">
<my-form-directive my-model="name"></my-form-directive>
<my-data-directive my-model="name"></my-data-directive>
<p ng-show="name">Controller $scope.name={{name}}</p>
</div>
Upvotes: 0
Reputation: 69
Adding a watch inside the MainCtrl should work when $scope is removed.
Change: $scope.$watch('[$scope.menuForm.name.$viewValue]'
to $scope.$watch('[menuForm.name.$viewValue]'
Another option would be to pass a callback into your directive.
Example Fiddle: http://jsfiddle.net/rfkjLst3/13/
<div class="m" ng-controller="MainCtrl">
<div>Main Ctrl</div>
<h3>(Shared Scope)</h3>
<directive1></directive1>
<directive2></directive2>
<hr />
<h3>(Isolate Scope)</h3>
<directive3 on-update="onUpdate(newVal, oldVal, $scope)"></directive3>
<directive4 some-var="updateVar"></directive4>
</div>
function MainCtrl($scope) {
// Shared Scope
$scope.name = '';
$scope.latestValue = '';
$scope.onChangeFn = watchFn; // Callback for shared scope directive
// Watching from Main Ctrl
$scope.$watch('[menuForm.name.$viewValue]', MainCtrlWatch, true);
// Isolate Scope
$scope.updateVar = '';
$scope.onUpdate = function updateFn(newValue, oldValue) {
$scope.updateVar = newValue || '';
console.log('hi',newValue, oldValue, $scope);
}
}
app.directive('directive1', function ($window) {
var directive = {
link: link,
restrict: 'EA',
template: '<div class="d"><b>Directive 1</b>' +
'<form name="menuForm">' +
'<label for="name">What is your name: </label>' +
'<input name="name" ng-value="" ng-model="name" required>' +
'</form></div>'
};
return directive;
function link(scope, element, attrs) {
// Watch from inside Directive working using shared scope
scope.$watch('[menuForm.name.$viewValue]', scope.onChangeFn, true);
}
});
app.directive('directive2', function ($window) {
//Notice no scope: { ... } so the scope is the parents.
var directive = {
link: link,
restrict: 'EA',
template: '<div class="d d2"><b>Directive2</b> <br /> {{ latestvalue }}</div>'
};
return directive;
function link(scope, element, attrs) {}
});
app.directive('directive3', function ($window) {
var directive = {
link: link,
restrict: 'EA',
scope: {
onUpdate: '&'
},
template: '<div class="d"><b>Directive 3</b>' +
'<form name="menuForm">' +
'<label for="name">What is your name: </label>' +
'<input name="name" ng-value="" ng-model="name" required>' +
'</form></div>'
};
return directive;
function link(scope, element, attrs) {
scope.name = '';
// Watching from inside the directive and firing callback
scope.$watch('[menuForm.name.$viewValue]', function (newVal,oldVal,$scope) {
$scope.onUpdate({newVal: newVal, oldVal: oldVal});
}, true);
}
});
app.directive('directive4', function ($window) {
var directive = {
link: link,
restrict: 'EA',
scope: {
someVar: '='
},
template: '<div class="d d2"><b>Directive4</b> <br /> {{ someVar }}</div>'
};
return directive;
function link(scope, element, attrs) {}
});
Upvotes: 3