Got awarded Microsoft MVP fifth time in a row

Hello All,

I am very happy to share that I have been awarded as Microsoft Most Valuable Award fifth times in a row. In the evening, I received the most awaited mail

MVP2015First time, I received this award on 1st July 2011 in ASP.NET/IIS category and since then the award getting renewed in same category every year. I really like ASP.NET from the day I started my professional career and it has been evolved by the time and kept it self a step ahead with other  technologies.

This award is really meant a lot to me and this time I am more as completed five years (Half a decade) with it. I would like to thank each one of you for your support and candid feedback. It would not have been possible without you. I will put more efforts towards community and my blog to make it more useful for you in coming days.

Last year, I entered in parent hood and became a father of lovely son which made me away from community for some time. But thank to my wife who manages all the things pretty well. Thanks a lot to her and she is the actual winner.

Before concluding, I would like to specially thanks some of the legends Pinal Dave, Vinod Kumar, BalmukundMahesh Chand, Shiv Prasad Koirala, Gaurav Mantri and many more who motivates me.Some of my friends Dhananjay Kumar, Abhijit Jana, Amit Chaudhary,  Abhishek, Lokesh Vij, Sri, Sudeep.. and there is a long list, they all always lent me their support whenever I required.

At last, I would say that I’ll devote more time to community with the same intensity and share my knowledge in different ways and learn from all of you. Your feedback is utmost important for me that I’ll seek every time.

Cheers,
Brij

 

How to use Angular Filter in Controller, Factory, Service – Part 15

In last two posts, we explored about the Filters and saw that how easily we can create custom filter and use as Angular predefined filters. We have used these filters in views for a single as well as an array of items. And this is a normal scenario but there could be some cases where you need to use these filters in other components like Controllers, Factory, Services etc. I have seen many questions around this on different online forums. So I thought to discuss it in detail.

If you are new to Angular Filter or even if you have some idea about, I will highly recommend you to go through my below two earlier Posts then continue. In this post, I will use the same examples that I used in my previous two posts as well.

Exploring Filters in {{AngularJS}} – Part 13

Exploring Filters in {{AngularJS}} Contd. : Custom Filters – Part 14

Note – This post is a part of series of posts on AngularJS and it is fifteenth one. Click here to view all the post. Apart from that you can also use the navigation links for next and previous post in each post at the bottom to check all.

There are two ways to achieve it, we’ll discuss it in details.

First Way –

We can use a filter in a Controller by injecting $filter. The syntax looks like

function myController($scope, $filter)
{
...
$filter('<fliterName>')(<comma separated filter arguments>);
...
};

The above syntax is self explanatory. Lets see some examples

myangularapp.controller("mycontroller", function ($scope, $filter) {    
    $scope.filteredvalueUpperCase = $filter('uppercase')('brij');         
    $scope.filteredvaluelowercase = $filter('lowercase')('Mishra');
    $scope.filteredvaluecurrency = $filter('currency')('1250');
});

// HTML
<div ng-app="myangularapp" ng-controller="mycontroller">
    <span>
        Name - {{filteredvalueUpperCase}} {{filteredvaluelowercase}} <br />
        Prize Money : {{ filteredvaluecurrency}}
    </span>   
</div>

Above we can see that I have used three predefined filters (uppercase, lowercase, currency) and assigned the filtered values in new properties of $scope and later used it in view. Let’s see it running

NormalFiltersThe Filters worked as expected. Similarly we can use custom filters in Controller as well. Let’s see

myangularapp.filter('ConvertoPhone', function () {
    return function (item) {
        var temp = ("" + item).replace(/\D/g, '');
        var temparr = temp.match(/^(\d{3})(\d{3})(\d{4})$/);
        return (!temparr) ? null : "(" + temparr[1] + ") " + temparr[2] + "-" + temparr[3];
    };
});

myangularapp.controller("mycontroller", function ($scope, $filter) {
    // Custom Filter
    $scope.filteredphonenovalue = $filter('ConvertoPhone')('1234567891');
});

In above examples, We have seen the Filter applied on single item. Similarly we can use the filters that can be applied on an array as

myangularapp.filter('RemoveSpecialCharacters', function () {
    return function (items) {
        var filtered = [];
        for (var i = 0; i < items.length; i++) {
            var item = items[i];
            filtered.push(item.replace(/[^\w\s]/gi, ''));
        }
        return filtered;
    };
});

myangularapp.controller("mycontroller", function ($scope, $filter) {
    var textValues = ['ab$h#cde&fg@', 'ba$h#dcj&fe@k#', 'ab$hm*hdp&ef@', 'ab$h#cdj&hg$ed@'];
    // Filter applied on array of items
    $scope.filteredtextValues = $filter('RemoveSpecialCharacters')(textValues);
});

In the above example, I have applied the custom filter on array of items in controller. In the same way, pre defined filter can be used.

Using Filters in Factory, Service, Directives-

As controllers are specific to views on the other hand we write the service using Factory or Service that are available and used globally. There could be some situations where we need to apply a Filter in any of the above. Similar as controller, as we inject the $filter in controller function, we can pass the same Factory/Service as well. Let’s see quickly

In Factory

// Injecting Filter in Factor
myangularapp.factory("myCustomService", function ($filter) {
    return {
        filteredData: $filter('uppercase')('brij'),
        filteredDataAnotherWay: $filter('lowercase')('Mishra')
    };
});

In Service

// Injecting Filter in Service
myangularapp.service('myCustomServiceV2', function ($filter) {
    this.filteredData = $filter('uppercase')('brij');
});

So we can see here that using the filter in other components is also same as controller.

Now lets see another way of using the Filter in this components

Second Way –

In first way, we have invoked the Filter in the said components using $filter and provided the filter name as parameter. Which internally invoked the appropriate filter. As we know that in JavaScript, everything is function, so there must be some function getting executed with the provided parameter when we provide a Filter. Let’s explore that.

To explain it in better way, I will take an example of above where I created a custom filter name ConvertoPhone . While executing when we define it, it must be storing the filter somewhere and then later must be used from there to invoke when we use (using $filter in above examples). Right!!  Let’s see how it is stored

FilterAnotherWaySo here we see that a variable suffix with value ‘Filter’ . That is used while registering the Filter with name as

name + suffix => ‘ConvertoPhone’ + ‘Filter’ = ConvertoPhoneFilter

So here we can see the Filter is stored as ConvertoPhoneFilter. Now let’s see that How it is invoked

FiltersinAnotherWay-2In above code, it is creating the name of the filter (‘ConvertoPhone’ + ‘Filter’ = ConvertoPhoneFilter) and fetching the function to execute. It means we can inject ConvertoPhoneFilter directly. The same is true for predefined filters as well. Above code are part of Angular library. Let’s see the example

FilterAnotherwayExHere above we can see that instead of passing $filter in controller, we are passing all the Filters (predefined and custom) with the updated name that we discussed above. Here I passed three predefined and one custom filter and that we used as a normal JavaScript function.

Similarly we can pass the Filters in Factory, Service etc. Complete example in attached with this post.

Hope you have enjoyed the Post. Do share your feedback and if want to see anything specific.

Cheers,
Brij

Next Post ==>

Exploring Filters in {{AngularJS}} Contd. : Custom Filters – Part 14

This post is in continuation of my previous post regarding Filters. (Click here to go to previous post). In last post we discussed about the basics of Angular Filters and found that how easy is to use the predefined filters with examples. This post is also fourteenth post in the series of AngularJS and to see all the previous posts, click here In this post, we will be discussing about custom Filter, its uses and create a few custom ones. Also try to explore some more flavors of the filters. We discussed two main types of Filters in previous post, one that transforms an item in another format. And other that can be applied on array of items which produces another array after applying Filter .The resultant array could have same or less number of elements and contain same or transformed data . As we discussed in my earlier posts that Modules is Angular are like containers . It is a top level element and contains all the part of AngularJS. So every custom items must be registered with it. Same is true here as well. Let’s start creating a filter of first type We already saw some Filters like uppercase, lowercase, currency etc. Now we are going to create a Filter which currently does not exist. It takes a  string of numbers and convert into phone number format. Excited? Let’s start

 	var myangularapp = angular.module('myangularapp', []);
        myangularapp.filter('ConvertoPhone', function () {
            return function (item) {
                var temp = ("" + item).replace(/\D/g, '');
                var temparr = temp.match(/^(\d{3})(\d{3})(\d{4})$/);
                return (!temparr) ? null : "(" + temparr[1] + ") " + temparr[2] + "-" + temparr[3];
            };
        });

Here first we created an Angular module myangularapp. Then added a filter in that module – ConverttoPhone which takes an input parameter and converts that in Phone Number format. Inside the function, normal JavaScript code is written to transform the data. And we have added a custom filter with module. Now its time to use it. Let’s see the HTML first customfilter1-htmlHere we see that ConverttoPhone (red encircled) is used as similar to predefined filters and currently it is applied on a hard-coded value. Lets run that customfilterr1So it just converted the number in US phone number format as we wrote in JavaScript function. Disclaimer – This code is used to make you understand the concept. It should not be used on production environments as is. Please note that this filter cannot be applied on arrays or list of data. Let’s create the filter that applies on array of items and there we will also find the reason that why the above one can not be applied. So here we are going to create a filter that takes a list of items and removes special character from each item. Let’s see the JavaScript code

myangularapp.filter('RemoveSpecialCharacters', function () {
    return function (items) {
        var filtered = [];
        for (var i = 0; i < items.length; i++) {
            var item = items[i];
            filtered.push(item.replace(/[^\w\s]/gi, ''));
        }
        return filtered;
    };
});

Now here if see that then only difference from above that here the function takes input an array of items that internally iterated and each value is processed accordingly. Now lets see the HTML code customfilter-2Here in 1- we initialized an array textValues with a list of four values which contains special characters. 2- We applied the custom filter RemoveSpecialCharacters as Angular provided filter. Now lets run the code customfilter2-rHere we can see that the filtered items returned without any special character. One more point here that we saw in angular filters that there we have the ability to provide some more values to the filer separated by colon (:), how to do that in custom filter. It is very simple, have your custom filter created as CustomFiltersExSo we can add as many parameters as we need and these can be passed via colon (:) similar to pre defined filters. Hope you have enjoyed this post. Do let me know if you wan to get added something or have any suggestion. Cheers Brij

Exploring Filters in {{AngularJS}} – Part 13


AngularJS is one of the hottest technologies currently in market. Every web project built on any platform whether .NET, JAVA, PHP or any other, all are just embracing it. It is because the kind of power, flexibility, openness and many other awesome feature provided by Angular. But I would say even we are using this framework in most of our web applications, but we are not leveraging the real power of of many features.In this post, I am going to discuss about Filters.

This post is again in the series of Posts of AngularJS and it is thirteenth in the list. To go though the previous posts in the series, click here.

Filters is one of key features provided by AngularJS and almost used in every web application. In this post, we are going to explore Filters. We’ll start from basics then dig deep and create our own custom filter at the end.

What is Filter

Filter as the name suggests, filters the data that gets passed via it. In a simple word, it takes an array of items as input and filter it which results to another array of data with same or less number of items and in same or other transformed format. JavaScript also provides us capability to filter the data so let’s understand that before Angular Filter.  If we want to filter the data what should be required.

1- An array of data

2- A comparator which return true of false. It takes each element if comparator returns true then add in resultant array else leave that element.

In JavaScript, comparator takes three input parameters – Value of the element, index of the element, the array being traversed and returns true or false. We can also pass some more parameters based on our requirement and have our own custom logic.

So lets have a look on JavaScript filter. In this example, I have just provided comparator which checks whether the passed value is even or odd. The syntax of JavaScript filter is as

arr.filter(callback[, thisArg])

Here callback takes three arguments:

  1-  the value of the element
  2-  the index of the element
  3- the Array object being traversed

Let’s see an example. Here I am providing a comparator which returns true in case of even numbers.

function IsEven(element, index, array) {
    // Not using input parameters like index and array
    return (element %2 == 0);
}

var filtered = [530, 3, 8, 112, 11, 240, 43].filter(IsEven);

document.write("Filtered Value : " + filtered);

The above code is self explanatory. Here I created a comparator which returns true or false based on the condition and provided that in the filter. It returns – 530,8,112,240.

Note – This feature is of ECMA-262 standard and wont work on the which supports prior version.

Now we have understood the basics of filter and similar feature available with JavaScript. Let’s move to AngularJS.

Filters in AngularJS

As AngularJS provides us more power to do thing with less and simpler code, the same applies here as well. Let’s start exploring the filters and its uses.

Angular provides a very simple way to use a Filter. We need to provide a filter expression separated by pipe (|) and we can add many filters in one go, just by separating with pipe. Filters can be used as two ways in AngularJS

1- Take an item and transform on another format. Ex – uppercase, lowercase, currency, date .

2- Filters an array which results another array with same or transformed data as discussed earlier.

Filter of type 1 (Single item)-

We will see both in this post via an example and start from first one. Lets look at the code

Filter-TransformI have put some numbers in green and let’s discuss accordingly.

1- An input box to enter first name with Angular model firstName.

2- An input box to enter first name with Angular model lastName.

3- Here firstName that is entered in textbox is displayed with Filter uppercase which converts the text in uppercase, no matter in which case it is entered by user.

4- Here lastName that is entered in textbox is displayed with Filter lowercase which converts the text in lowercase, no matter in which case it entered by user.

5- Prize money is hard-coded here and currency Filter is applied.

Now lets see it running Filters1pngHere we can see that it is running as expected. First name is in upper case while last name is in lower case and Prize money transformed in currency format.

Filter of type 2 (An array of items)-

Let’s look the filter that applies while displaying list of data. So the code looks like

ng-repeatHere I have initialized some data then used that later for the demo. Let’s discuss each number mentioned in above code as earlier.

1- Initializing an array named courses which a list of course via ng-init.

2- Using ng-repeat to display all the items in array in tabular format.

3- Applied an order by attribute on the property name. Here name is provided in single commas as a value because Angular search that string in the items in provided array. Also there is one more value provided true, what is the use of that. Lets see the syntax of this filter

{{ orderBy_expression | orderBy : expression : reverse}}

So here the last item is reverse so if it true the items would be sorted in descending order else ascending order. And here we have set it is as true so it should be in descending order.

Now lets run that and see the output

Filters-RepeatSo here we can see the items is sorted in descending order based on the course name as expected. Let’s see one more exampleNG-REPEAT2Here I added search input and applied filter using that

1- Textbox to enter the search text.

2- Here I added a filter (named as filter) on the entered value in text box with model name searchText.

3- One more filter orderBy added as earlier example. it means here we have applied two filters and that is totally correct. We can apply as many filter as we want by separating via pipe (|). lets run thatFilters-repeat-2 Here W is entered in textbox and two rows shown which contained this characters. And you can observe that ordering is also working based on the filters provided.

So we can see that applying filter is very easy in Angular and it provides us a powerful way to display the data. In next post, we will discuss about writing custom Filters and their uses.

Cheers,
Brij

A Great unification of Controllers: ASP.NET 5

This is another post on one of the cool features of ASP.NET 5. Microsoft introduced One ASP.NET concept with ASP.NET 4.5 which allows us to use MVC, Web API, Web forms in one project without any pain. But as we know that MVC and Web API follow the same coding constructs like controller, action but inherently they were different. There were some features like OutputCache (Refer one of my earlier post ) is available only with MVC not with Web API. Microsoft has redesigned ASP.NET MVC and Web API framework and made it truly one ASP.NET with vNext (ASP.NET 5). Now we can use the same controller to expose as an web-api endpoint and for returning the MVC views as well. As these are using the same framework now, all the features available with MVC can be seamlessly used with web api as well and vice versa.  Let’s have a pictorial look

Earlier versions of ASP.NET

All the MVC controllers are derived from Controller class under the name space System.Web.Mvc.

ControllersEarlierSimilarly Web API controllers derived from ApiController which belongs to the namespace System.Web.Http

APIController

With ASP.NET 5 –

NewControllerIn ASP.NET 5, Controller is part of namespace Microsoft.AspNet.Mvc and all the controller derives from this. These can be used either MVC controller or Web API controller or a combination of both as shown in above picture.

Note – With ASP.NET 5, Microsoft releases another version of MVC as ASP.NET MVC 6. In this post, I have referred MVC 6 many times based on the context.

Let’s explore it via example. We will create a simple asp.net mvc 6 application. We’ll start from asp.net 5 empty application.

  1. File -> New Project -> ASP.NET Web Application -> Type <Project name>.

  2. Select empty application from ASP.NET Preview templates and click Ok

  3. Now open project.json and add Microsoft.AspNet.Mvc in dependencies

  4. Create controllers, views and models folder in the solution as it is required by an MVC app

  5. Add a controller say HomeController

  6. Add a folder Home in Views and create an MVC View Index in it

  7. Now open startup.cs and add MVC in ConfigureServices method and use that in Configure method there and provide the default route.

I have added Index method at HomeController as

public ActionResult Index()
{
    ViewBag.Message = "Message set at server at " + System.DateTime.Now.ToLongTimeString();
    return View();
}

and the view looks like

@{
    // ViewBag.Title = "Home Page";
}
<h2>My MVC View</h2>
@ViewBag.Message

Let’s run our application-
FirstMVC

It is working as expected. We have just a created a normal ASP.NET MVC 6 application from an ASP.NET 5 empty solution.

 

 

Now we are going to use the same controller to add web api methods as well. We just need to add web api method as

[HttpGet]
public IEnumerable<string> Get()
{
    return new string[] { DateTime.Now.ToLongTimeString(), DateTime.UtcNow.ToLongTimeString() };
}

Now this method is available as api can be called as per requirement. Let’s use it as

<input type="button" value="Call Api" onclick="LoadData();" />&nbsp;
<div id="dvapidata"></div>

<script src="http://code.jquery.com/jquery-1.11.3.min.js"></script>
<script>
    function LoadData() {
        $.ajax({
            type: "Get",
            cache: false,
            url: "/Home/Get",
            contentType: "application/json; charset=utf-8",
            data: "{}",
            dataType: "json",
            success: AjaxSucceeded,
            error: AjaxFailed
        });

    }
    function AjaxSucceeded(result) {
        $('#dvapidata').html(result);
    }
    function AjaxFailed(result) {
        alert('no success');
    }
</script>

Here I added a  method which initiates a jQuery Ajax call which calls the web api method that we added and put the result in div after request completes. To initiate the ajax call, we added a button on the page. Let’s run the application
MVCnWebAPI

Here we got the same MVC View and when we click on Call API button which call web api method via jQuery ajax. The response is encircled on the screenshot.

So we can see here that the same controller is used as MVC and Web API controller both. It is true one ASP.NET.

 

Some More Features

Let’s add some more flavors to this controller. To access the controller, we need to define the route templates that we defined in startup.cs. Let’s comment out that and just put app.usemvc() there as

startupAs we don’t have any route there so we need to define it at some other places. You might recall one more way of defining routes – attribute routing that got introduced with ASP.NET MVC 5. It is available here as well with some more cool enhancements. Let’s explore that

  • We can define the routes at controller and action as
    asp.net5riutesHere we can see that I have just put the route as /[controller] at class level, this is a generic route which take the name of the controller (Here Home),so even if the name of the controller changes we don’t need to change the route. Similarly, we provided the route definition on the action.
  • To define multiple or default routes, we can add more route to the controller as
    multiroyes
    Here we have given two routes to the controller one is already discussed above and other is a default route. So if user doesn’t give the controller name, it will take as Home. Similar we did for action as well. So now we can access this url as http://localhost:20199/home/index and http://localhost:20199/ both.
  • We can have different routes for different actions in the controller as
    DiffRoutes  In above screenshot, we can see that we gave two different routes on two action method of the same controller.

Note –  In ideal scenario, it is not good to use the same controller as MVC controller and Web API controller but they are now exactly same and in certain scenarios can be used. But the mail beauty of it that all the features available in MVC can be used seamlessly in MVC and Web API both

Hope you have enjoyed the post. Do share your feedback

Cheers
Brij

 

OutputCache doesn’t work with Web API – Why? A solution

Output Cache is one of the most useful features of ASP.NET and plays a key role for making high performance web applications. It’s very easy to use this feature. Just put OutputCache attribute on any controller/action or you can set outputCacheSettings attribute in web.config. ASP.NET MVC and ASP.NET Web API are two technologies that looks very similar when we work with them. They have similar concepts like Controller, Action, routing etc and work almost in similar way except one returns View and returns data in JSON/XML format.

Recently in an application, I was required to cache some web api calls so I put the OutputCache attribute over the Web API action but when I ran it was not working. The data was not getting cached and on every request, it was going to server and further fetching data from database and returning the same. Then to verify the attribute, I put the same attribute over a MVC action and it was working like a charm. So I felt that it looks like that this attribute is not working.

It made me bit irritated and I was expecting that it should give an error if it is not supported then. I had an impression that all the features available with MVC also works with Web API and vice versa. Let’s have a look with an example

1- I have created a TestController (MVC) and Index View.

2- Then I am assigning current time in ViewBag and displaying in the view.

3- Then I decorated the Action with OutputCache attribute. Let’s see the code

    public class TestController : Controller
    {
        [OutputCache(Duration = 20, VaryByParam = "none", Location = OutputCacheLocation.ServerAndClient)]
        public ActionResult Index()
        {
            ViewBag.Message = "Message set at server at " + System.DateTime.Now.ToLongTimeString();
            return View();
        }
    }

We saw the TestController above. Let’s look at Index View

@{
    ViewBag.Title = "View";
}
<h2>My MVC View</h2>
@ViewBag.Message

It’s simple.Now lets run it

cachedmvcAs here we can see that the time is not getting updated after multiple refreshes. This is very expected behavior that we want from the attribute.

Now let’s See the Web Api part.
1- I created a TestDataController which inherits from ApiController.
2- It has a Get method which return a list of string. Here for simplicity, it contains two items- DateTime in normal and UTC format.
3- Here I also decorated with OutputCache attribute to the Web API method as I did in MVC example.
4- Then I created another MVC action (Details) in TestController and created a View accordingly.
5- Now from the Details view, I am calling the web api via jQuery Ajax.

Let’s quickly have a look at the code

public ActionResult Details()
{
    return View();
}

Web API Controller :

    public class TestDataController : ApiController
    {
        [OutputCache(Duration = 20, VaryByParam = "none", Location = OutputCacheLocation.ServerAndClient)]
        public IEnumerable<string> Get()
        {
            return new string[] { DateTime.Now.ToLongTimeString(), DateTime.UtcNow.ToLongTimeString() };
        }
    }

Above controller has the same OutputCache attribute.

MVC View:

<h2>Details</h2>
<input type="button" value="Call Api" onclick="LoadData();"/>&nbsp;
<div id="dvapidata"></div>

<script src="~/Scripts/jquery-1.10.2.js"></script>
<script>
    LoadData();
    function LoadData() {
        $.ajax({
            type: "Get",
            url: "/api/TestData",
            contentType: "application/json; charset=utf-8",
            data: "{}",
            dataType: "json",
            success: AjaxSucceeded,
            error: AjaxFailed
        });

    }
    function AjaxSucceeded(result) {
        $('#dvapidata').html(result);
    }
    function AjaxFailed(result) {
        alert('no success');
    }
</script>

Now let’s run that and have a look

webapinocache

 

Oh.. here the data is not cached and time is getting updated in every call which is not expected.

Let’s analyze why it did not work for Web API

To get the details, I tried to dig it further to see details of the HTTP request and response for both (MVC and Web API). Let’s have a look that I collected via fiddler

ResponseHeadersSo clearly we can see in the left side (Red encircled area) that Cache header is set properly which is response header for MVC action, while in the right side, we see that (Blue encircled area), Cache control is set as no-cache. It means OutputCache attribute is not setting the proper cache header in response for web api.

To solve this we can created our own custom filter the adds the appropriate header at web api call as we saw above so that it can be cached at client and then decorate that attribute at Web  API call. Lets create that

    public class CacheWebApiAttribute : ActionFilterAttribute
    {
        public int Duration { get; set; }

        public override void OnActionExecuted(HttpActionExecutedContext filterContext)
        {
            filterContext.Response.Headers.CacheControl = new CacheControlHeaderValue()
            {
                MaxAge = TimeSpan.FromMinutes(Duration),
                MustRevalidate = true,
                Private = true
            };
        }
    }

In the above code, we have overridden OnActionExecuted method and set the required header in the response. Now I have decorated the Web API call as

  [CacheWebApi(Duration = 20)]
        public IEnumerable<string> Get()
        {
            return new string[] { DateTime.Now.ToLongTimeString(), DateTime.UtcNow.ToLongTimeString() };
        }

Now let’s run the application.

CachedwebApiIt is working as expected and the response is getting cached. Lets see the response header via fiddler now

WebApiHere see the blue encircled area, cache header is set. So this is the reason response is getting cached now.

Hope you have enjoyed the post and it has helped you.

Cheers
Brij

Few ways to pass values to a Function in Isolate scope : {{AngularJS}} – Part 12

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 –

  1.  Creating custom directive in AngularJS – Part 9
  2.  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

expressionAs 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

firstoptionWe 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.

ThirdOptionNote – 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