Custom Directives in AngularJS is pretty vast topic. I thought of covering it in a single post but as I started writing, count is just increasing as I don’t want to leave any important and relevant aspect. This is third post on custom directive and twelfth post in the series of AngularJS (Click here to see all the post). Till Now, we have discussed that how to create a basic custom directive in first post then in second , we discussed about creating custom directive with isolate scope. The link of those two posts are below –
- Creating custom directive in AngularJS – Part 9
- Create Custom Directive using Isolate scope in AngularJS – Part 10
In my last post, I discussed about various options available while creating isolate scope in custom directives and three different types of Local Scope properties. These are
1) @ or @attr
2) = or =attr
3) & or &attr
In this post, I am going to discuss more about the third option. It allows us to wire up some external expression to the custom directive as discussed in the last post. Let’s see the pic from last post about the third option in isolate scope
As the primary benefit of the custom directive is re-usability and to get the most benefit out of it , we need to use isolate scopes. Apart from that, it is common where we need to pass some values to the external function. Although Angular does not provide any direct way to achieve it but there some other workarounds. Let’s start exploring
Here we are passing UpdateData expression in the isolate directive. Now let’s see what should we do if we want to pass some values in this method. There could be multiple ways, I am going to discuss a few.
First Option: In this scenario, let’s say we have some data that is available in the custom directive itself that we need to send to in external expression as parameter. For this, I added an input text box in template that I will be using the entered value as parameter for the external function. Let’s first see the directive
<expcustomdirective expr="UpdateData(updatedName)" talkname="{{talk.name}}" />
Here I am passing a parameter named updatedName in UpdateData. So let’s change the method accordingly
$scope.UpdateData = function (modifiedName) { $scope.talk = { name: modifiedName, duration: '45m' }; };
Now let’s see the custom directive
myangularapp.directive('expcustomdirective', function () { var directive = { restrict: 'E', // restrict this directive to elements scope: { method: '&expr', talkname: '@' }, template: "<input type='text' ng-model='mytalkName'/><div>{{talkname}}</div> <input type='button' " + "ng-click='method({updatedName : mytalkName})' value='Update Data'/> " } return directive; });
In the template above, I added an input text box and provided the model (ng-model) name as myTalkName .Another important point (ng-click) to see here, how the value is passed. Here we need to provide an object map so that it gets bound correctly as {updatedName : mytalkName}. Now, Lets see it running
We can see here that we can easily get a value that is part of custom directive itself and use it in external expression.
Second Option – We discussed in first option that how can we pass some value which is generated from the directive itself. Lets take another scenario, where you need to pass the values that is available outside.
We know that the compilation process involves two steps in Angular – One is compiling and another is linking. Linking has the responsibility to assign the scope to directive. We can take the help of linking function to pass some values in the external function. While writing to custom directive, we can attach a function to link as
link: function (scope, element, attrs) {
}
This gets called once for the custom directive. Here it has three parameters.
scope – It is the isolated scope that is available for the directive.
element – It is a custom directive element.
attrs– List of attributes available in custom directive.
So lets update our custom directive .
var myangularapp = angular.module("myangularapp", []); myangularapp.directive('expcustomdirective', function () { var directive = { restrict: 'E', // restrict this directive to elements scope: { method: '&expr', talkname: '@' }, template: "<div>{{talkname}}</div> <input type='button' " + "ng-click='method(updatedName)' value='Update Data'/> ", link: function (scope, element, attrs) { scope.method({ updatedName: "Updated topic name" }); } } return directive; });
See the link part in above code , It is calling the external expression that got assigned to method property of isolate scope and passing the parameter as you can see above. Here also the parameter is passed using object map. But here if we run the the page, then this method will be called by default called as link will be executed while load.
Third approach – This is similar approach with above but we will further enhance it. As I discussed above that attrs contains all the attributes of the custom directive. So we can set some value in attribute that we can read later. Let’s see with an example
<expcustomdirective expr="UpdateData(updatedName)" talkname="{{talk.name}}" talknewname ="Update Talk name via attribute"/>
So here I added an attribute as TalkNewName that we will use and pass it in the expression. Let’s see How?
myangularapp.directive('expcustomdirective', function () { var directive = { restrict: 'E', // restrict this directive to elements scope: { method: '&expr', talkname: '@' }, template: "<div>{{talkname}}</div> <input type='button' " + "ng-click='method({updatedName : NewTalkName})' value='Update Data'/> ", link: function (scope, element, attrs) { scope.NewTalkName = attrs.talknewname; } } return directive; });
In above code, if we see the link function then here, we are creating a new property (named NewTalkName) in isolated scope and assign value from the attribute (See inside link). Now again, if we see ng-click in the code, I am mapping the argument name with new property added in the scope. Let’s run it.
Note – AngularJS converts camel-case to snake-case when moving from JavaScript to HTML or vice-versa. Like if you added an attribute with name talkNewName, it will be accessed id JavaScript by talknewname only. I spent lots time to figure it out.
So in this post, different work around of passing values in the external expression. It can be helpful in many different scenarios. You yourself can explore some other options if it does not serve your need but there is no direct way in AngularJS . Above code may also not look very intuitive but it solves the purpose. Complete example is attached.
Hope you have enjoyed the post. To navigate to previous and next post of the series, use the links at the bottom of the post.
Cheers
Brij
Hi, well explained. Can I know when are you planning to post the blog regarding the dependency injection and testing capability in Angular JS?
Pingback: ASP.NET MVC and Angular Routing together – Part 11 | Code Wala
Pingback: Exploring Filters in {{AngularJS}} – Part 13 | Code Wala