Angular Directive Isolate Scope Binding with Parameters

(First off, sorry for the long winded post title. It is basically what I google every time I’m trying to remember the functionality.)

Let’s say you have a directive that allows a user to enter data. When that user is done entering data, the directive processes the data, then sends the result back up to the parent. If we were to do this with two-way data binding, we’d have to set up watchers to know when the values were changed. There is a way to do it without the watchers though. We can use the parent scopeĀ binding type: “&”.

In the world of Angular Directives, a lot has been written about two way scope variable binding, but I always seem to have difficulty when using scope bound variables. That is, scope variables that are bound with “&*. The Angular docs define it as:

& or &attr – provides a way to execute an expression in the context of the parent scope. If no attr name is specified then the attribute name is assumed to be the same as the local name. Given <widget my-attr=”count = count + value”> and widget definition of scope: { localFn:’&myAttr’ }, then isolate scope property localFn will point to a function wrapper for the count = count + value expression. Often it’s desirable to pass data from the isolated scope via an expression to the parent scope, this can be done by passing a map of local variable names and values into the expression wrapper fn. For example, if the expression is increment(amount) then we can specify the amount value by calling the localFn as localFn({amount: 22}).

This means we can call a function in our directive’s isolate scope that maps to the directive’s parent scope without having to know anything about it!

Let’s setup a parent controller and a basic input directive that will return an uppercase value when completed:


angular
.module('myApp', [])
.controller('MyController', MyController)
.controller('MyDirectiveController', MyDirectiveController)
.directive('myAwesomeDirective', myAwesomeDirective);
function MyController() {
var vm = this;
vm.myValue = 'Initial Value';
vm.updateValue = function(value) {
vm.myValue = value;
};
}
function MyDirectiveController() {
var vm = this;
vm.buttonClick = function() {
var value = vm.directiveValue.toUpperCase();
// Note: param is `valueToUpdate` not `value` since we
// defined it as `valueToUpdate` in the html parameter
vm.updateFunction({valueToUpdate: value});
}
}
function myAwesomeDirective() {
var template = '<input class="form-control" type="text" ng-model="vm.directiveValue">';
template += '<button class="btn btn-warning" ng-click="vm.buttonClick()">Update!</button>';
return {
restrict: 'E',
controller: 'MyDirectiveController',
controllerAs: 'vm',
bindToController: true,
scope: {
updateFunction: '&'
},
template: template
};
}

Our implementation looks like this:


<!DOCTYPE html>
<html ng-app="myApp">
<head>
<script data-require="angular.js@1.4.7" data-semver="1.4.7" src="https://cdnjs.cloudflare.com/ajax/libs/angular.js/1.4.7/angular.min.js"></script>
<link rel="stylesheet" href="style.css" />
<link rel="stylesheet" href="//maxcdn.bootstrapcdn.com/bootstrap/3.3.5/css/bootstrap.min.css" />
<script src="script.js"></script>
</head>
<body>
<div ng-controller="MyController as vm">
<h1>My Value: {{ vm.myValue }}</h1>
<my-awesome-directive update-function="vm.updateValue(valueToUpdate)">
</my-awesome-directive>
</div>
</body>
</html>

The main takeaway here is the update-function="vm.updateValue(valueToUpdate)" line. This is what passes the parent’s updateValue function to the directive. Also, you’ll see that I’ve used “valueToUpdate” in the html file, while the parameter in the main controller is just “value”. This was just to emphasize the linkage between the directive controller and the directive parameter. The “updateValue” function in the main controller still keeps the parameter named “value”.

There is also a working plunker example of our code below:

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out /  Change )

Twitter picture

You are commenting using your Twitter account. Log Out /  Change )

Facebook photo

You are commenting using your Facebook account. Log Out /  Change )

Connecting to %s