AngularJS: Sometime OrderBy does not work in ng-repeat

You must noticed that sometime OrderBy does not works, sometime works very nicely.

For example: if you have the data with following structure:
JavaScript

$scope.friends = [
      { name: 'John', phone: '555-1212', age: 10 },
      { name: 'Mary', phone: '555-9876', age: 19 },
      { name: 'Mike', phone: '555-4321', age: 21 },
      { name: 'Adam', phone: '555-5678', age: 35 },
      { name: 'Julie', phone: '555-8765', age: 29 }
];

Then it works if you code use the following code:
HTML

<tr ng-repeat="friend in friends | orderBy:'-age'">
      <td>{{friend.name}}</td>
      <td>{{friend.phone}}</td>
      <td>{{friend.age}}</td>
    </tr>

But if your data structures changes a bit as follows:
JavaScript

$scope.peoples = [{
      'friend':{ name: 'John', phone: '555-1212', age: 10 },
      'relative':{ name: 'Mary', phone: '555-9876', age: 19 },
      'cousin':{ name: 'Mike', phone: '555-4321', age: 21 },
      'uncle':{ name: 'Adam', phone: '555-5678', age: 35 },
      'aunt':{ name: 'Julie', phone: '555-8765', age: 29 }
}];

HTML

<tr ng-repeat="people in peoples | orderBy:'-age'">
      <td>{{people.name}}</td>
      <td>{{people.phone}}</td>
      <td>{{people.age}}</td>
</tr>

Now, order by will not. This is because, previous data structure was an array and order by works fine on array. Now it is an Object. Order by does not works on Objects. So, first you have to make this objects to an array and then it will fine.

To make this object to an array we will use an filter. Following code will create an filter for throughout the module:
JavaScript

 ng.module('yourmodule').filter('toArray', function() {
  return function(obj, addKey) {
    if (!(obj instanceof Object)) {
      return obj;
    }

    if (addKey === false) {
      return Object.values(obj);
    } else {
      return Object.keys(obj).map(function(key) {
        return Object.defineProperty(obj[key], '$key', {enumerable: false, value: key});
      });
    }
  };
});

Now you just add this filter to html code:
HTML

    <tr ng-repeat="people in peoples | toArray | orderBy:'-age'">
      <td>{{people.name}}</td>
      <td>{{people.phone}}</td>
      <td>{{people.age}}</td>
    </tr>

😉 Order by will work like magic. Cheers!

View complete code in Plnkr.co

Advertisements

AngularJS: Add enter key to check/uncheck the check box

Sometimes clients want something different. We all know that if we check/uncheck the check box through keyboard then we have do it by space bar. But sometimes clients wants this through enter key in addition to the space bar specially for keyboard only user. So, this code can reduce your effort to write your own.

For AngularJS:

// Assume that your main module name is app, it can be anything you like.
var App = angular.module('app', []);

// Adding as directive.
App.directive('input', ['$interval', function($interval) {
    return {
      restrict: 'E', // It restricts that the directive will only be a HTML element (tag name), not an attribute.
      link: function(scope, elm, attr) {
        if (attr.type === 'checkbox') {
          elm.on('keypress', function(event) {
            var keyCode = (event.keyCode ? event.keyCode : event.which);
            if (keyCode === 13) {
              event.preventDefault(); // only when enter key is pressed.
              elm.trigger('click');
              scope.$apply();
            }
          });
        }
      }
    };
  }
]);

Same thing on jQuery is pretty easy:

jQuery(document).ready(function() {
  jQuery('input:checkbox').keypress(function(event) {
    var keyCode = (event.keyCode ? event.keyCode : event.which);
    if (keyCode === 13) {
      event.stopPropagation(); // only when enter key is pressed.
      this.trigger('click');
    }
  });
});

Very Basics of Angular JS

Recent years was a bright year for JavaScript developers, many JavaScript frameworks were born. With the advent of these frameworks, it can be quite a pain for developers to choose one suitable framework. Today we will talk with another JavaScript framework, which is Angular JS. This is very basic level discussion to kick start the Angular JS SPA (Single Page Application) Development.

Angular JS claims itself as super heroic JavaScript framework. Angular enhances HTML for web apps. It has functionalities to ease the process of developing web apps. HTML was first intended to build dynamic web apps that are Angular. Angular is what HTML would have been if it were designed to build web apps.

Before dig deeper to Angular features, we want to let you know that Angular is brought to you by Google. At least this fact can give you assurance Angular comes from the right people you can trust.

A strong understanding of basic JavaScript will be required to use Angular. If you feel that you’re beginner, keep going, Angular is not necessarily for advanced developers, but you will be dealing with a lot of objects so you have to be familiar with object oriented paradigm in JavaScript.

Digging into Angular JS:

– Angular JS is such a powerful SPA framework which allows writing client side application without JS coding or JS knowledge.

  • Here is an example how a simple app can be built without having any JS code.

– Angular JS is a full featured SPA Framework. It has all that needs for a good SPA[Single Page Application].

– So, the Big Picture of the Angular JS is like follows:

– Now, digging more deeper-

  • Directives and Data Binding: Directives refers to a feature to extends the vocabulary of HTML, it also can be seen as a way to teach your browser new tricks . With directive feature, we can create new HTML vocabulary that the browser will understand what it means and what it should do. You will find here all directives: http://docs.angularjs.org/api/ng#directive

  • View & Controller: between view controller there is a term $scope. Scope is a glue between view and controller. We also can call it Dependency Injector.

– Controller doesn’t know about the view. So, when a view calls a controller, it injects the scope automatically.

– View can be a full body DOM or a particular div. Different div can be used as different view in same html. Here the scope is the div in which the controller has declared.

  • Module:

– In Big Picture of Angular JS we saw Module is the root of everything. For a single page only one module can be added, but module can add many other module inside it by mentioning the dependencies or other module.

– Here is how module is defined with and without dependency- [We call it Dependency Injection]

  • Routers: In a configuration we can define the router. Router takes the URL after a “#” and loads related views. View can be defined in different html file.

  • Factories: factories are similar to Data-Model. There are four things in Angular JS for manage data. These are Factory, Service, Provider, Value.

Caman JS – an amazing library for JS lovers

I found an amazing JS library for image processing. This is very effective JS but little slower. The specialty is it works in browser as well as with node JS. So you can make an image processing tool for Android/iOS by JS now. You will find more details on their site: http://camanjs.com/ but here I experimented myself for browser. Here is the simplest code example for learning the very basic in couple of minutes. You may love it.

Download from here.

ExtJS: Horizontal sliding style paging for long panel using jQuery

Here we will see Horizontal sliding style paging for long panel using jQuery. Though in Horizontal sliding style paging for long panel [Part-2] and Horizontal sliding style paging for long panel [Part-1] we saw sliding with having scroll bar as viewable. In this part we will see how we implement a Horizontal sliding style paging for long panel without scroll bar.

There must have some other way. But, using jQuery seems easy and efficient to me. You can have a look How to use jQuery with ExtJS. Because, here I will show just the codes I used.

In my previous tutorials I told that the inner contents (Grid panels for my case) is dynamically added. So i don’t know the exact width.

So what i have to do is:

  1. Calculate the window width
  2. Calculate how many grids can be showing per slide
  3. Shift the Left position to slide the Inner Grids

Now, lets start coding.

ExtJS view Settings:

    Ext.define('MyProj.view.AllPacksPanel', {
    extend: 'Ext.panel.Panel',
    alias: 'widget.allpackspanel',
    title: 'All Packs',
    layout: 'hbox',
    id: 'allpackspanel',
    ...

overflowX: 'scroll' has been removed, because default value is hidden.

And the buttons:

    dockedItems: [{
        xtype: 'toolbar',
        dock:'bottom',
        items: [
        {
            text: '',
            iconCls: 'icon-page-prev',
            id:'allpackspanel-page-prev'

        },
        '->',
        {
            xtype : 'tbtext',
            text : 'Page 1 of 1',
            id:'allpackspanel-page-number'
        },
        '->',
        {
            text: '',
            iconCls: 'icon-page-next',
            id:'allpackspanel-page-next'
        }
        ]
    }]

You may have noticed all handler we have removed.

For jQuery add an anonymous function, which will protect inner codes from outer scope and we will be able to avoid conflict.

(function (jQuery) {
    //my codes will go here...
})(jQuery);

Now I will add some variable so that in future we can use less effort to modify anything.

    var prevEl = '#allpackspanel-page-prev-btnEl'; //next button id
    var nextEl = '#allpackspanel-page-next-btnEl'; //prev button id
    var pageNumberEl = '#allpackspanel-page-number'; //id for: in the middle of these 2 button page number shows.
    var showButtonEl = '#show-packs-btnEl'; // this button was used to load the grids inside the panel
    var gridEl = '.x-panel.x-grid'; //common grid classes
    var viewContainerEl;
    var viewContainerElId='#allpackspanel-body';  //parent panel body
    var viewableWidth;
    var totalInnerWidth;
    var innerViewEl;
    var innerViewElId='#allpackspanel-innerCt'; //inner div in the panel body
    var positionLeftX = 0;
    var elWidth = 300; //width for each grid
    var moveDelta = 5; // how much grid will be moved per slide
    var totalEl=0;  //totla grids
    var currPage = 1;
    var totalPage = 1;
    var moveFactor = parseInt(moveDelta * elWidth); //the exact pixel to move finally

Now adding button actions.
As contents are adding dynamically, we will use jQuery on() function to bind elements dynamically.

    //grid loading button action
    jQuery(document).on('click', showButtonEl, function(){
        updateEl();
        updateVars();
        currPage = 1;
        updateViewableArea();
    });
    //next button action
    jQuery(document).on('click', nextEl, function(){
        updateEl();
        updateVars(); 
        if(++currPage <= totalPage){
            updateViewableArea();
        }else{
            currPage = totalPage;
        }
    });
    //prev button action
    jQuery(document).on('click', prevEl, function(){
        updateEl();
        updateVars();
        if(--currPage > 0){
            updateViewableArea(-1);
        }else{
            currPage = 1;
        }
    });

We see here few functions (updateEl(), updateVars() and updateViewableArea()) which are still not defined. So lets define those.

    function updateEl() {
        //each time we need update the elements
        //because element may replaced with new one.
        //if you are sure then you can use only in loader button's action
        viewContainerEl = jQuery(viewContainerElId);
        innerViewEl = jQuery(innerViewElId);
    }
    
    function updateVars() {
        totalEl = viewContainerEl.find(gridEl).length;
        
        viewableWidth = parseInt(viewContainerEl.width(),10);
        moveDelta = parseInt(viewableWidth / elWidth);
        
        totalPage = parseInt((totalEl / moveDelta),10);
        if(totalEl % moveDelta) totalPage++;
    }

    function updateViewableArea(direction) {
        if (typeof direction == "undefined" ) 
            direction = 1;

        var prevPos = viewableWidth * direction;

        var show = 0;
        for(var i=0; i < totalEl; i++){
            if(i < (currPage * moveDelta) && i >= ((currPage - 1) * moveDelta)){
                viewContainerEl.find('.x-panel.x-grid').eq(i).css({
                    'left':prevPos+'px'
                }).show().animate({
                    'left':(show * elWidth)+'px'
                },500);
                show++;
            }else{
                viewContainerEl.find('.x-panel.x-grid').eq(i).hide();
            }
        }
        jQuery(pageNumberEl).text('Page '+currPage+' of '+totalPage);
    }

We are done. But, if the inner contents are grid panels then the hidden grids will miss something. Like header and footer buttons etc.

But if we show hide with the EXT object then it wont happened.

    var id = viewContainerEl.find('.x-panel.x-grid').eq(i).attr('id');
    Ext.getCmp(id).show();
    Ext.getCmp(id).hide();   

So lets change the code:

    function updateViewableArea(direction) {
        if (typeof direction == "undefined" ) 
            direction = 1;

        var prevPos = viewableWidth * direction;

        var show = 0;
        for(var i=0; i < totalEl; i++){
            var id = viewContainerEl.find('.x-panel.x-grid').eq(i).attr('id');
            if(i < (currPage * moveDelta) && i >= ((currPage - 1) * moveDelta)){
                Ext.getCmp(id).css({
                    'left':prevPos+'px'
                }).show().animate({
                    'left':(show * elWidth)+'px'
                },500);
                show++;
            }else{
                Ext.getCmp(id).hide();
            }
        }
        jQuery(pageNumberEl).text('Page '+currPage+' of '+totalPage);
    }

Now, we can see fully animated and functional Horizontal sliding style paging..

Please, feel free for any kind of suggestion or discussion….

ExtJS: Horizontal sliding style paging for long panel [part-2]

In Part-1 I showed how we can use scrollBy(). In this part-2 we will see how we can do it with Position.

Panel Settings as before:

Ext.define('MyProj.view.AllPacksPanel', {
    extend: 'Ext.panel.Panel',
    alias: 'widget.allpackspanel',
    title: 'All Packs',
    layout: 'hbox',
    id: 'allpackspanel',  //this is the ID we will use to get the component in button handler
    overflowX: 'scroll',  //horizontal scroll will be shown
    ...
    ...

Button with handler.

	dockedItems: [{
        xtype: 'toolbar',
        dock:'bottom',
        ui: 'footer',
        items: [
        {
            text: 'prev'
           iconCls: 'icon-prev'
           handler: function() {
               var cmp = Ext.getCmp("allpackspanel");
               var pos = cmp.getPosition();
               cmp.setPosition(pos[0]+300,pos[1],true);
           }
        },
        '->',
        {
            text: 'next'
           iconCls: 'icon-next'
           handler: function() {
               var cmp = Ext.getCmp("allpackspanel");
               var pos = cmp.getPosition();
               cmp.setPosition(pos[0]-300,pos[1],true);
           }
        }
        ]
    }]

The difference with scrollBy() in nothing at all. You may be noticed that both of this have the scroll bar is visible. If we Disable the scroll bar then this function will have no effect. But, seeing scroll bar is annoying. So We will see in Horizontal sliding style paging using jQuery how we can hide the scroll bar and make a smooth sliding like this.

ExtJS: Horizontal sliding style paging for long panel [part-1]

There are several ways to achieve Horizontal sliding style paging for a panel which is horizontally larger than window. Here in part-1 I will show how to use scrollBy() . For my case there are more than 20 Grid panel was added in a Panel. FYI: I used the MVC architecture of ExtJS.

I have added two button at bottom (Next and Prev) to move the scroll. So the code was like bellow:

Panel settings was:

Ext.define('MyProj.view.AllPacksPanel', {
    extend: 'Ext.panel.Panel',
    alias: 'widget.allpackspanel',
    title: 'All Packs',
    layout: 'hbox',
    id: 'allpackspanel',  //this is the ID we will use to get the component in button handler
    overflowX: 'scroll',  //horizontal scroll will be shown
    ...
    ...

And code for button with handler:

    dockedItems: [{
        xtype: 'toolbar',
        dock:'bottom',
        ui: 'footer',
        items: [
        {
            text: 'prev'
           iconCls: 'icon-prev'
           handler: function() {
               var cmp = Ext.getCmp("allpackspanel");
               cmp.scrollBy(-300,0,true);
           }
        },
        '->',
        {
            text: 'next'
           iconCls: 'icon-next'
           handler: function() {
               var cmp = Ext.getCmp("allpackspanel");
               cmp.scrollBy(300,0,true);  //300 as I want it will scroll by inner inner grid where inner grid panel size is 300
           }
        }
        ]
    }]

We will see in Part-2 how we can do the same with the position.

Regular expression for URL validation

Some times we may need to validate the URL from back-end or front-end.

I used following codes and works good for me. You can check it once if you need.

So for PHP

    function is_valid_url($url) {
        return preg_match('/^((ht|f)tp(s?)(:\/\/))?([a-z0-9-]+[.]{1})+[a-z0-9-]+(:[0-9]*)?(\/{1}[a-zA-Z0-9\-\.\?\,\:\!\'\/\\\+&amp;%\$#_=]+)*\/?$/i', $url);
    }

And for JS

    function is_valid_url(url) {
        var urlregex = new RegExp(/^((ht|f)tp(s?)(:\/\/))?([a-z0-9-]+[.]{1})+[a-z0-9-]+(:[0-9]*)?(\/{1}[a-zA-Z0-9\-\.\?\,\:\!\'\/\\\+&amp;%\$#_=]+)*\/?$/i);
        return urlregex.test(url);
    }

This will allow following pattern of URL
http://www.abc.com
http://www.abc.com:8080
http://www.abc.com:8080/abc.xyz?a=2&b:c#!landingpage
https://www.abc.com
http://www.abc.com
http://www.abc.com/path/
http://www.yahoo.com/path/to

Encapsulated anonymous functions in JavaScript

In several place we see some syntax like (function(){})(). What actually it means?

Well will see some very basic example of function writing pattern, with which we are more familiar.

For example, one creates a named function like this:

function finc1(){
alert('normal func');
}
finc1();

but we can write the same function in different way, like we create an anonymous function and assign it to a variable:

var finc1 = function(){
alert('anonym func assigned in a var');
};
finc1();

So, now if we think in different way as follows:

(function(){
alert('anonym func executing immediately');
})();

Here, it encapsulates a block of code by creating an anonymous function, then wrapping it in brackets and executing it immediately.
So what did we get from here? The function are created and called immediately, we just removed one step according to previous one. So, we can assume that the previous function and this function are same. But still there is a difference, that is we have encapsulated it with braces. So the vars and function declared inside of this encapsulated area will not be accessible from outside. But there also have some way that we can inject an object in to it. Which can carryout the encapsulated functions within the object we injected if we want, The following code are sample for that:

(function(j){
alert(j);
})(k);

Here encapsulated function have a parameter j and it passes k immediately where k is expected defined previously.