Sunday, August 16, 2015

AngularJS ngOption Directive Simplified

With AngularJS, we can use the ngOption directive to dynamically create the options that are available from the select input field. There are a few ways to use this directive and depending on the application requirements, we may choose one from another. Let’s try to simplify its usage by using some practical examples:

Demo Preview:  (see working demo below)



Bind to a String Array:

We can use this approach to bind a list of strings as options. Both the input value and text take on the array value. When an option is selected, the Value is set to the model defined by the ngModel Directive. When we look at the result from Selected Option 1 (see demo below), we can see how the selected option text is also the selected option value.

Expression
ng-options="option for option in ctrl.makes"
Description
Use the string as both value and text.

Bind to Collection of Objects:

This approach provides more flexibility since it allows us to bind to more than just a Value/Text reference. We can use an object as an option, and when the option is selected, this object is assigned to the model defined by the ngModel Directive. This means that in addition to the value, we have access to all other properties of this object. Let’s look at Seleted Option 2 (demo). As we select a value from the select control, we can see the output display the JSON contained by the object.

Expression
ng-options="car as car.model for car in ctrl.cars"
Description
Use a car object as value, use the model attribute as text.

Bind to Collection of Objects with Explicit Attributes as Key/Value Pairs:

This approach allows us to use a collection with key/value nodes. This provides the flexibility to explicitly indicate what attributes from the object should be the text and value. It also uses simple data types for the binding, so only the attributes used in the ngOption directive are assigned. If we look at Selected Option 3, we can see that the value contained in the id property is displayed.

Expression
ng-options="car.id  as car.model for car in ctrl.cars"
Description
Use attribute id as value and model as text.

Bind to Collection of Objects with Explicit JSON:

This approach is similar to the previous one, but it allows us to indicate that we may just want to use some attributes in a JSON structure from the object and only assigned those to the model. In Selected Option 4, we can see how we are only using a couple of attributes from the object and creating a JSON to map them. This is then assigned as an object to the model.

Expression
ng-options="{model:car.model,id: car.id } as car.model for car in ctrl.cars track by car.id"
Description
Use JSON declaration and assigned only the attributes id and model. Use model as text. The selected value is determined by card.id

Track Selected Object:
One important item to note when using the ngOption directive with complex types is that we need to explicitly indicate what attribute should be used to track the selected option. This is done with the expression “track by”.  If this is not properly assigned, the selected text does is not displayed even though an object assignment is actually made. See Selected Option 5.

Expression
ng-options="{model:car.model,id: car.id } as car.model for car in ctrl.cars"
Description
Use JSON declaration and assigned only the attributes id and model. Use model as text. There is no tracking of the value, so no text is displayed.

Demo:





Well I hope this provides some clarifications on how to use the ngOption directive.

Tuesday, July 14, 2015

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.

Sunday, July 12, 2015

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.