In an AngularJS application I have a parent directive and a child directive.
angular
.module('myApp')
.directive('customForm', function(customService, apiV1, Constants, $timeout) {
return {
restrict: 'E',
scope: {
param1: '=',
param2: '=?',
boolean1: '@?'
},
template,
link: function(scope, parentController) {
scope.data = customService.newClient;
//some stuff...
angular
.module('myApp')
.directive('customToolForm', function () {
return {
restrict: 'E',
scope: {
name: '=',
city: '=',
postalCode: '='
},
template,
controller: function ($scope, $rootScope, Constants, apiV1, customService) {
$scope.doSomethingWithPostalCode = function() {
$scope.$parent.doSomethingWithPostalCode();
}
//some stuff...
<address-client-creation name="data.client.name" city="data.client.city"
postal-code="data.client.postalCode">
</address-client-creation>
<input maxlength="5" type="text" data-ng-model="postalCode"
data-ng-change="doSomethingWithPostalCode();">
The issue I have is that :
When the method doSomethingWithPostalCode
is triggered from the childDirective, the value of the postalCode in the child is not the same as the client.postalCode of the parent, but at the end of the method it is.
it seems that the two way binding event that update the parent value is happening after the function call
So my question is what is the best way to ensure that the $parent scope is updated before calling the method?
The AngularJS framework implements two-way ('='
) binding by adding a watcher to the child scope which transfer the data from the child scope to the parent scope. The watcher requires a digest cycle to detect the change and do the transfer.
A more modern approach is to use one-way ("<"
) binding for inputs and expression ("&"
) binding for outputs:
app.directive('customToolForm', function () {
return {
restrict: 'E',
scope: {
name: '<',
city: '<',
̶p̶o̶s̶t̶a̶l̶C̶o̶d̶e̶:̶ ̶'̶=̶'̶
postalCode: '<',
postalCodeChange: '&',
},
template: `
<input maxlength="5" type="text" data-ng-model="postalCode"
data-ng-change="doSomethingWithPostalCode(postalCode);">
`,
controller: function ($scope, $rootScope, Constants, apiV1, customService) {
$scope.doSomethingWithPostalCode = function(postalCode) {
̶$̶s̶c̶o̶p̶e̶.̶$̶p̶a̶r̶e̶n̶t̶.̶d̶o̶S̶o̶m̶e̶t̶h̶i̶n̶g̶W̶i̶t̶h̶P̶o̶s̶t̶a̶l̶C̶o̶d̶e̶(̶)̶;̶
$scope.postalCodeChange({$event: postalCode});
}
//some stuff...
Usage:
<custom-form-tool
name="data.client.name" city="data.client.city"
postal-code="data.client.postalCode"
postal-code-change="data.client.postalCode=$event; doSomething($event)"
>
</custom-form-tool>
Using expression ("&"
) binding immediately makes the event data available to the parent controller.
It also makes the migration path to Angular 2+ easier.
For more information, see