Filtering arrays in AngularJS

Previously I wrote an article on how to display data from a simple javascript array using AngularJS.

Following on from that this next article will show you how to filter that same array by particular properties.

In the previous article I used the following HTML markup with AngularJS to loop through an array of users to display their Name and Location:

<div ng-app="myApp" ng-controller="myController">
    <ul>
        <li ng-repeat="user in users">{{user.Name}} | {{user.Location}}</li>
    </ul>
</div>

If we wish to filter this array by users only located in England then we can pass a filter to the ng-repeat property such as:

ng-repeat="user in users | filter:{Location:'England'}"

Filter by multiple properties in AngularJS

If we wish to filter by multiple properties we can extend the filter object to include a second property:

ng-repeat="user in users | filter:{Location:'England', Gender:'M'}"

This will filter the array by users with a Location of “England” and a Gender of “M”.

Filter by complex conditions

Sometimes you may wish to filter your array by more complicated conditions.

For example you might have an array of users, and each user has an array of posts they’ve made.

var data = [
    {
        Name: "John Smith",
        Gender: "M",
        Location: "Wales",
        Posts:[
            {
                date: "Jan 2015",
                message: "lorem ipsum"
            },
            {
                date: "Mar 2015",
                message: "lorem ipsum"
            }
        ]
    },
    .....
];

If you need to filter by users who have made a post in June 2015 this could be abstracted into a Custom Filter.

myApp.filter("UserFilter", function(){

    return function(users, postDate){

        var addUser;
        var selectedUsers = [];
        for(i=0;i<users.length;i++){

            addUser = false;

            for(j=0;j<users[i].Posts.length;j++){
                if(users[i].Posts[j].date == postDate){
                    addUser = true;                    
                }
            }

            if (addUser){
                selectedUsers.push(users[i]);
            }
        }

        return selectedUsers;
    };

});

Then this can be added to the ng-repeat statement:

<li ng-repeat="user in users | UserFilter: 'June 2015'">

See Demo: http://jsfiddle.net/py9g1L1k/1/

Using multiple parameters with custom AngularJS filters

You might wish to also filter by the user’s location. In which case a second parameter can be passed to the ng-repeat attribute using a colon (:):

<li ng-repeat="user in users | UserFilter: 'June 2015':'England'">

Then the custom filter can be changed to accept a 3rd parameter and include additional logic to filter by the location:

myApp.filter("UserFilter", function(){

    return function(users, postDate, location){

        var addUser;
        var selectedUsers = [];
        for(i=0;i<users.length;i++){

            addUser = false;

            if (users[i].Location == location){

               for(j=0;j<users[i].Posts.length;j++){
                   if(users[i].Posts[j].date == postDate){
                       addUser = true;                    
                   }
               }

               if (addUser){
                   selectedUsers.push(users[i]);
               }

            }
        }

        return selectedUsers;
    };

});

Setting up a simple AngularJS app to display an array

AngularJS is a powerful Single-Page-Application javascript framework created by Google.

The following is a simple tutorial on how to set up an AngularJS application to display a javascript array of user information.

First of all we’ll start by creating our javascript array. The following is an array of user information containing details of Name, Gender and Location.

var userData= [
    {
        Name: "John Smith",
        Gender: "M",
        Location: "Wales"
    },
    {
        Name: "Sally Smith",
        Gender: "F",
        Location: "USA"
    },
    {
        Name: "Curtis Timson",
        Gender: "M",
        Location: "England"
    },
    {
        Name: "Sam Wallace",
        Gender: "M",
        Location: "England"
    },
    {
        Name: "Caroline James",
        Gender: "F",
        Location: "Scotland"
    }
];

Next we’ll set up the HTML application container required:

<div ng-app="myApp"></div>

We can then initialise this as an Angular application by calling angular.module(). This will become the scope of our application. Therefore our myApp will not be able to influence HTML outside of this container.

var myApp = angular.module("myApp", []);

Now that the application has a variable, myApp, we can add a controller to it and create a new variable containing the user data:

myApp.controller("myController", function($scope){
   $scope.users = userData; 
});

Therefore $scope.users now references our original array of user data.

Going back to our HTML, we can now back a reference to the controller:

Within this div element we can now access the users variable. Therefore we can create an unordered list element, and by using ng-repeat create a loop of list items. AngularJS uses {{ }} to be able to access properties of the current object in the loop.

<div ng-app="myApp" ng-controller="myController">
    <ul>
        <li ng-repeat="user in users">{{user.Name}} | {{user.Location}}</li>
    </ul>
</div>

Here we are looping through all user in users to display multiple li elements and display the Name and Location of each user.

And that’s it!

Below is a working example of the above tutorial I’ve put together on jsFiddle. Feel free to edit it and play around.

How to store razor helpers globally

ASP.NET MVC Razor helpers are a great way of reducing duplicated code by containing code snippets in a View which can then be called multiple times.

<div>
    @DisplayGreeting("Curtis")
</div>

@helper DisplayGreeting(string name)
{
    <span>Hello @name</span>
}

However what if you wish to call this same helper on another View?

In which case the helper can be stored in a seperate View in the “App_Code” folder.

For example create a new View in the “App_Code” folder called “MyHelpers.cshtml”:

HelpersSolutionExplorer

Move the helper code into this file:

MyHelpersView

Then the helper can be called from the previous view by using MyHelpers.DisplayGreeting:

<div>
    @MyHelpers.DisplayGreeting("Curtis")
</div>

This way any View within the same ASP.NET MVC Application can then make use of this helper.

Managing @font-face definitions with LESS

A typical @font-face definition looks something like this:

@font-face {
  font-family: 'CustomWebFont';
  src: url('customwebfont.eot');
  src: url('customwebfont.eot?#iefix') format('embedded-opentype'),
       url('customwebfont.woff2') format('woff2'),
       url('customwebfont.woff') format('woff'),
       url('customwebfont.ttf')  format('truetype'),
       url('customwebfont.svg#svgFontName') format('svg');
  font-weight:normal;
  font-style:normal;
}

Here we are defining the font’s name, weight, style, and providing various file types for cross-browser compatibility.

If a web application is using different web fonts, or even a different weight/style (bold/italic) for the same web font, then this code has to be practically repeated several times.

This goes against DRY methodology and results in increased maintenance and management.

However, using LESS mixins we can abstract these properties making the definitions more readable.

Add the following to your LESS file:

.font-face(@font-family, @filepath, @font-weight, @font-style){
    @font-face {
        font-family: @font-family;
        src: url('@{filepath}.eot');
        src: url('@{filepath}.eot?#iefix') format('embedded-opentype'),
            url('@{filepath}.woff2') format('woff2'),
            url('@{filepath}.woff') format('woff'),
            url('@{filepath}.ttf')  format('truetype'),
            url('@{filepath}.svg#svgFontName') format('svg');
        font-weight:@font-weight;
        font-style:@font-style;
    }
}

Then, for the example above, this can be used as follows:

.font-face('CustomWebFont', 'customwebfont', normal, normal);

If we want to use 4 different type-faces for this web font then it is simply just 4 lines to write:

.font-face('CustomWebFont', 'customwebfont', normal, normal);
 .font-face('CustomWebFont', 'customwebfont_bold', bold, normal);
 .font-face('CustomWebFont', 'customwebfont_italic', normal, italic);
 .font-face('CustomWebFont', 'customwebfont_bolditalic', bold, italic);

This would then output the following in our rendered CSS:

@font-face {
  font-family: 'CustomWebFont';
  src: url('customwebfont.eot');
  src: url('customwebfont.eot?#iefix') format('embedded-opentype'), url('customwebfont.woff2') format('woff2'), url('customwebfont.woff') format('woff'), url('customwebfont.ttf') format('truetype'), url('customwebfont.svg#svgFontName') format('svg');
  font-weight: normal;
  font-style: normal;
}
@font-face {
  font-family: 'CustomWebFont';
  src: url('customwebfont_bold.eot');
  src: url('customwebfont_bold.eot?#iefix') format('embedded-opentype'), url('customwebfont_bold.woff2') format('woff2'), url('customwebfont_bold.woff') format('woff'), url('customwebfont_bold.ttf') format('truetype'), url('customwebfont_bold.svg#svgFontName') format('svg');
  font-weight: bold;
  font-style: normal;
}
@font-face {
  font-family: 'CustomWebFont';
  src: url('customwebfont_italic.eot');
  src: url('customwebfont_italic.eot?#iefix') format('embedded-opentype'), url('customwebfont_italic.woff2') format('woff2'), url('customwebfont_italic.woff') format('woff'), url('customwebfont_italic.ttf') format('truetype'), url('customwebfont_italic.svg#svgFontName') format('svg');
  font-weight: normal;
  font-style: italic;
}
@font-face {
  font-family: 'CustomWebFont';
  src: url('customwebfont_bolditalic.eot');
  src: url('customwebfont_bolditalic.eot?#iefix') format('embedded-opentype'), url('customwebfont_bolditalic.woff2') format('woff2'), url('customwebfont_bolditalic.woff') format('woff'), url('customwebfont_bolditalic.ttf') format('truetype'), url('customwebfont_bolditalic.svg#svgFontName') format('svg');
  font-weight: bold;
  font-style: italic;
}

Using @font-face and preventing faux-styles

@font-face is used in CSS to define a custom font style for a web page.

Some custom fonts come with multiple type-faces for different weights and italic styles.

These are often defined with seperate font-family names for each type-face.

For example the “Alegreya” font could be defined as:

@font-face{
    font-family:'alegreya';
    src: url('Fonts/Alegreya-Regular.otf');
    font-weight: normal;
    font-style: normal;
}

@font-face{
    font-family:'alegreya-bold';
    src: url('Fonts/Alegreya-Bold.otf');
    font-weight: normal;
    font-style: normal;
}

@font-face{
    font-family:'alegreya-italic';
    src: url('Fonts/Alegreya-Italic.otf');
    font-weight: normal;
    font-style: normal;
}

This would then be applied in areas of CSS as such:

div{
    font-family:'alegreya';
}

div{
    font-family:'alegreya-bold';
}

div{
    font-family:'alegreya-italic';
}

The issue here is that unless another developer is aware, applying font-weight:bold; to the “alegreya” font-family will result in the browser applying it’s own faux-bold styling rather than using the custom “Alegreya-Bold.otf” type-face. Likewise with italic styling.

The browser’s interpretation of bold/italic will never be as nice as the custom designed type-face.

Below is an example of the browser’s interpretation of italic vs the “Algreya-Italic.otf” file:

Browser Italic:
browser-font

Type-Face Italic:
type-face-italic

The best way to avoid this is to use the same font-family name for each definition.

For example:

@font-face{
    font-family:'alegreya';
    src: url('Fonts/Alegreya-Regular.otf');
    font-weight: normal;
    font-style: normal;
}

@font-face{
    font-family:'alegreya';
    src: url('Fonts/Alegreya-Bold.otf');
    font-weight: bold;
    font-style: normal;
}

@font-face{
    font-family:'alegreya';
    src: url('Fonts/Alegreya-Italic.otf');
    font-weight: normal;
    font-style: italic;
}

This can then be used by keeping the same font-family but adjusting the weight/style applied:

div{
    font-family:'alegreya';
}

div{
    font-family:'alegreya';
    font-weight:bold;
}

div{
    font-family:'alegreya';
    font-style:italic;
}

Preventing console.log issues in IE

In some older browsers, including versions of Internet Explorer, window.console doesn’t exist and therefore calling console.log() will result in an error.

One way of fixing this is to create a function which checks whether console exists and use this function instead:

function consolelog(v){
    if (window.console
        && window.console.log){
        window.console.log(v);
    }
}

However this requires all developers knowing about this function, and if someone forgets and directly calls console.log() then older browsers will still throw an error.

Therefore a better solution is to check whether console.log() exists, and if not, create an empty function which prevents the error occurring.

if (!(window.console
    && window.console.log)){
    window.console = {
       log:function(v){return;}
    }
}

Alternatively a better shorthand method would be:

window.console = window.console || {log:function(a){}};

Round to the nearest decimal

If we need round to the nearest whole number, we can use the Math.round() function to return this:

Math.round(1.34234); //returns 1

However what if we need to round to a decimal place? For example 0.5.

The following function can be used to do just that, and the logic itself can be adapted to be used for other languages too (C#, SQL etc).

function roundToMultiple(value, multiple){
    var t = (1/multiple);
    return (Math.round(value*t)/t).toFixed(2);
}

This can then be used like so:

roundToMultiple(1.34234, 0.5);  //returns 1.50
roundToMultiple(1.34234, 0.25); //returns 1.25
roundToMultiple(1.34234, 0.1);  //returns 1.30
roundToMultiple(1.34234, 0.05); //returns 1.35

It can also be used to round to values greater than 1:

roundToMultiple(25.3423423, 4); //returns 24.00

Mixing Revealing Module and Singleton Javascript Patterns

Until recently I’ve been using the Singleton pattern for my javascript objects.

This works well as my functions are namespaced and therefore the risk of clashing object names across Javascript files is reduced.

For this example I’ve created a singleton pattern javascript object which will show an alert window displaying “hello world”.

var MyFunction = {
   Init: function(){
      this.Config.foo = "hello world";
   },
   Config:{
      foo:null
   },
   ShowAlert:function(){
      alert(this.Config.foo);
   }
}

MyFunction.Init();
MyFunction.ShowAlert();

View Demo

With this object it’s possible for me to change the value of foo so that the alert displays a different message.

MyFunction.Init();
MyFunction.Config.foo = "lorem ipsum";
MyFunction.ShowAlert();

View Demo

However, what if I didn’t want it to be possible to change foo outside of the MyFunction object itself? This is where the “Revealing Module” javascript pattern comes in use.

Using the Revealing Module pattern we can encapsulate “private” functions and expose only the functions that we wish to.

var MyFunction = function(){

    var foo = null;

    function Init(){
      foo = "hello world";   
    }

    function ShowAlert(){
     alert(foo);   
    }

    return {
        Init: Init,
        ShowAlert: ShowAlert
    };
}();

MyFunction.Init();
MyFunction.ShowAlert();

View Demo

With this pattern only Init and ShowAlert are exposed outside of the object. Outside the scope of MyFunction its not possible to change foo.

This works great, but I believe it loses the organisation and scale-ability of the singleton pattern.

Therefore we can change the functions in MyFunction to use a Singleton pattern and expose functions from with this inner object using the Revealing Module pattern:

var MyFunction = function(){

    var _ = {
       Init: function(){
          _.Config.foo = "hello world";
       },
       Config:{
          foo:null
       },
       ShowAlert:function(){
          alert(_.Config.foo);
       }
    }

    return {
        Init: _.Init,
        ShowAlert: _.ShowAlert
    };
}();

MyFunction.Init();
MyFunction.ShowAlert();

View Demo

Another additional benefit of this mixed pattern is that we can have a complex singleton structure, which can expose particular functions with more “friendly” names.

Using our existing example, ShowAlert might be nested inside other objects:

var MyFunction = {
   Init: function(){
      this.Config.foo = "hello world";
   },
   Config:{
      foo:null
   },
   UI:{
        Display:{
            ShowAlert:function(){
                alert(MyFunction.Config.foo);
            }
        }
    }
}

With the Singleton pattern we would have to call MyFunction.UI.Display.ShowAlert.

With the Module/Singleton pattern this can be exposed as just ShowAlert despite its more complex position in the object structure.

var MyFunction = function(){

    var _ = {
       Init: function(){
          _.Config.foo = "hello world";
       },
       Config:{
          foo:null
       },
       UI:{
            Display:{
                ShowAlert:function(){
                    alert(_.Config.foo);
                },
            }
        }
    }

    return {
        Init: _.Init,
        ShowAlert: _.UI.Display.ShowAlert
    };
}();

MyFunction.Init();
MyFunction.ShowAlert();

View Demo

I’m still reasonably new to adopting this Singleton/Module pattern mix-up, so if you have any suggestions or questions, all comments are welcome!

What is cache busting?

A cache-buster is a unique string which is appended to a URL in the form of a query string.

It is generally not read by the server-side and is used purely to form a unique URL. For example:

/Scripts/foo.js?v=1

This is often used on client side files such as Javascript, CSS and Images in order to force a browser/cache-system to retrieve the latest version of a file from its source.

When a webpage is downloaded, any associated files are also downloaded and stored in the browser’s cache. This is for performance purposes so that the webpage doesn’t have to download the files every time the page is refreshed.

However, as a developer, if you are to make a change to any of those files, you need to ensure the client will download the latest version.

Therefore the cache-buster query string can be updated so that the browser doesn’t recognise the file in it’s cache and downloads a new version.

Here a different types of cache-buster methods you can use:

Static Cache-Buster

When the file is updated, all references to the file could be manually updated to increment a version number.

For example:

<script type="text/javascript" src="/Scripts/foo.js?v=1"></script>

Becomes:

<script type="text/javascript" src="/Scripts/foo.js?v=2"></script>

However this isn’t a clean solution because this task will have to be carried out every time the file is updated. And in cases where its forgotten, browsers will potentially still use an older version of the file.

Date/Time Cache-Buster

The current date/time could be appended to the reference so that every call to the webpage will return a unique cache-buster. For example this can be done like so in .NET MVC:

<script type="text/javascript" src="@string.Format("/Scripts/foo.js?v={0}", DateTime.Now.Ticks)"></script>

However this won’t be great for performance, and defeats the point of browsers caching files at all.

Software Version Cache-Buster

Another method of cache-busting is to use the Software Version of the application. This ensures that whenever a new version of the application is deployed, the cache-buster will be updated:

<script type="text/javascript" src="/Scripts/foo.js?v=2014.9.25.75285"></script>

The down-side to this method is that a change could be made to the application which creates a new version number even when a change to the file has not been made. In which case the browser would download the file again when it already has the file stored locally in cache.

Hashed-Content Cache-Buster

My preferred method of cache-busting is to create a hash of the content and use this as the cache-buster.

This is the same method that ASP.NET MVC Bundling & Minification uses for it’s cache-busting.

<script type="text/javascript" src="/Scripts/foo.js?v=r0sLDicvP58AIXN_mc3QdyVvVj5euZNzdsa2N1PKvb81"></script>

The advantage of this is that you could set a really long max-age value, such as a 1 year, in your Cache-Control header and be confident that this won’t be persisted once the content has changed.


Whichever method you choose, cache-busting is a great way to ensure your clients are using the most up-to-date version of your files.

Quickly create HTML elements in jsFiddle

In case you haven’t already heard of it, jsFiddle is a web application which allows you to enter HTML, CSS and Javascript into different windows and render the output. It’s a great tool for testing various front-end concepts, and then “fiddles” can be saved and shared.

Because of this feature it’s a popular tool on StackOverflow for demonstrating issues/solutions.

One feature I’ve come across is the ability to quickly create elements in the HTML window by using CSS selectors. This makes jsFiddle even more quick and easy to create demos!

For example if I write the following in the HTML window:

div#a.b

And then hit tab, this will be converted to:

<div id="a" class="b"></div>

Awesome!

This can be taken a step further to include nested elements:

div#a.b>span.c

Which will produce:

<div id="a" class="b"><span class="c"></span></div>

Or we can create multiple nested elements:

div#a.b>span.c+span.d

Which will produce:

<div id="a" class="b"><span class="c"></span><span class="d"></span></div>

Finally we can also add other attributes in the same way we would select them in CSS:

a[href='http://curtistimson.co.uk']

Which produces:

<a href="http://curtistimson.co.uk"></a>

jsfiddle

© 2015 Curtis Timson

Theme by Anders NorenUp ↑