7/14/15

AngularJS Data Grid with Paging

With AngularJS, we can easily display a data grid with some data by just binding a JSON model to a view. In cases where the data is somewhat large, we would like to provide users with a much better experience by adding paging to the grid.  We should note that the purpose of this article is to show a technique for client side paging. For much larger data sets, this approach may not be recommended.

With AngularJS, paging can be done with the use of a custom filter and service. The filter enable us to control the data (subset) that should be displayed on each page. The service is used by the controller to manage the paging commands like previous, next and to update the model that is used by the filter to know when to show a corresponding set of data based on the current page selection. We should take a look at the following code snippet and result to see how things work, and we can then cover the details of the implementation.



As we can see in the result tab, as we press the paging buttons the grid displays only the records for the selected page (shown on the footer).  We can also change the default page size from the select box and either select 5 or 10.  Let’s cover the implementation in more detail.

Filter:

The filter basically just slices the array to return a subset of data for the selected page. The filter is placed on the ng-repeat mark-up and takes three parameters (items : data, page: current page, onPage: page size).

Service:

The service provides the model and actions that are used by the user interface elements. It is injected into the controller (app.grid) to make it available to the mark-up. This is what allows the user to page through the data and reset the page size setting. It also provides pager status like current page, number of pages and total number of records. On the controller, we set a reference of the service (ctrl.pager).

The View:

On the view, we access the paging service using the ctrl.pager property of the controller. This exposes the properties and methods of the paging service. Review the HTML tab and take a look at the HTML mark-up to see how this is done.

How this works:

As the user interacts with the paging elements (page size, previous and next buttons), the properties of the service are updated. This causes the filter (ng-repeat directive) to update again with the new paging values which can be a page changed or page size changed.


I hope this is able to show how simple paging can be implemented as a reusable service that can be injected into controllers.

7/12/15

AngularJS Data Grid with Filters

AngularJS ability to bind a model to a view can be leveraged to design very interactive user interfaces that can help improve the user experience. A very common user interface enhancement is to allow users to filter the data that they are working on.  We can easily build such feature in our applications with the use of the $filter service.

To illustrate the use of the $filter service, we can build a basic vehicle inventory on a data grid. We need the user to filter on this data by typing a text on a particular column. We can enable this by adding text boxes on the header of each column on the grid. The purpose of the text boxes is to allow the users to type text that can be used to filter that data that is currently displayed.



Looking at the AngularJS controller (gridCtrl), we see that we are using the filteredList property as the model for our view. On the initial load, the filteredList contains all the current items. As the user types information on any of the header text boxes (onchange), we filter the data by using the $filter service and passing the search model which binds to each text box. This enables the $filter service to match only the items that have the filter criteria. This also allows us to apply multiple search filters. For example, we could look for all 1999 Toyota vehicles only, and the result should look as follows:

Data Grid with Filters
Data Grid with Filters


This approach allows us to filter data from the data grid without any server side traffic. This approach is only recommended for data sets of a few hundreds. For much larger data sets, a server side filter would be recommended.


I hope that provides some ideas on UI designs with AngularJS.

6/27/15

ANGULARJS Print Bootstrap Modal Content

When trying to print a modal dialog, we may not need to see the main layout content mixed with the modal content on the print out.  This is however the default behavior when we try to print a web page.

In order to print the modal dialog content, we need to hide the main layout and only make the dialog content visible. This can be achieved by adding print media styles which only affect the print out and not the screen media.  Let’s look at a printing a simple invoice example shown below:

Print modal content


Note that in this example, we have two actions/buttons:


Print Modal Dialog:  Prints out the modal dialog content only.    
                                                  
Normal Print: Prints out the entire web page.



For the Print Modal action, we add the print media styles to hide the entire content of the page. This allows us to prevent the layout elements to be visible in the print out. We also need to print the modal content. To do that, we add a style class (print-content) and attributes to the Bootstrap .modal class which allows us to override the default modal style. As a result, only the dialog content is shown on the print out.

We should note that this approach is not specific to AngularJS. It is a technique that can be used with any JS framework as the changes are specific to CSS classes and not the framework.

Thanks for reading.

Originally posted at ozkary.com

6/13/15

ANGULARJS Calculate Totals Using Directives


In this article, we show how to do a calculation of subtotals and totals using AngularJS. To illustrate how we can do the aggregates, we build a simple invoice in which we will add the total quantity of items and subtotals per item and final amount. 

We first start by showing the JSON model that represents a list of items with quantity and cost per unit. These are the amounts that we will be adding using directives.



$scope.items = [{
    name: 'Baseball Bats',
    quantity: 2,
    unitCost: 75
}, {
    name: 'Soccer Balls',
    quantity: 5,
    unitCost: 15
}, {
    name: 'Baseball Gloves',
    quantity: 3,
    unitCost: 40
}];


As shown in the JSON model, there is quantity and cost information, but we need to add a new attribute that can provide the total for each item by using this simple formula (quantity * unitCost). We also need to provide a total amount for both the sum of items and cost.

In order to meet our goal, we use the ng-repeat and ng-init directives. The ng-repeat directive allows us to iterate every item in the list. The ng-init directive allows us to execute an expression or call a function for each item. This is what enable us to extend the model by adding attributes that hold the total amounts. We can see this with the following code snippets:



The setTotals function in the invoice controller calculates each item total. It also uses the invoiceCount and invoiceTotal scope variables to aggregate (sum) the quantity and total for all items.  This is what allows us to generate a total row in the grid.

I hope this post provides you with more ideas on how to deal with calculated values using AngularJS.


5/24/15

AngularJS Value Mapping With Dynamic Property And JavaScript

In some scenarios, the JSON models that we have available on the client browser may not provide all necessary information for our view templates. A record may just have a numeric value which makes reference to another model in the system, and we need to be able to map or look up for that information. To illustrate this, let’s look at a dealership inventory vehicle list:

Models:

$scope.cars = [{ model: 'Altima', year: 2015, make: '1' },
            { model: 'XTerra', year: 2015, make: '2' },
            { model: 'Focus', year: 2015, make: '3' }];

$scope.makes = [{ id: 1, name: 'Toyota' },
                { id: 2, name: 'Nissan' },
                { id: 3, name: 'Ford' }];

The models show a list of makes and vehicles that any dealership may have an inventory. We want to build a view that shows the vehicle list. When using the cars list and the help of the ng-repeat directive as show below, we get this result.



As we can see, there is no Make 1,2,3. That is the MakeId. We would like to display the name instead. The problem with this is that the cars list only has the id, so we need to implement a look up with the makes list.  A way to do this is to create a dynamic property with the Make name on the cars list. This can be accomplished by using the ng-init directive which allows us to use an expression or call a JavaScript function.


The ng-init directive calls the controller function to initialize each row in the list. The function performs the look up in the make list and adds the new property makeName which is used on the HTML mark up.

We should note that this approach was done using ng-init directive and a function on the controller (JavaScript). Another approach can be done using the ng-repeat directive and a filter right on the HTML mark up. Read more here.


Thanks for reading.