1/20/18

Angular filtering on multiple options using anonymous functions

When building web applications using grid or list views, we often have the need to filter the data based on a selected option.  With AngularJS this is a trivial task as we can use a filter to select the data, but it gets tricky when we need to provide the same functionality using multiple filter options. With this article, we take a look at implementing a multi-option filter using anonymous functions.



Defining the model


For our demo app, we build a simple vehicle inventory viewer which can filter results by selecting one or more makes. The vehicles associated to our checked selections should be displayed.


var list = [
    { "id": 1, "year": 2018, "make": "Nissan", "model": "Altima" },
    { "id": 2, "year": 2018, "make": "Nissan", "model": "XTerra" },
    { "id": 3, "year": 2018, "make": "Subaru", "model": "Outback" },
    { "id": 4, "year": 2018, "make": "Subaru", "model": "Crosstrek" },
    { "id": 5, "year": 2018, "make": "Toyota", "model": "4Runner" },
    { "id": 6, "year": 2018, "make": "Toyota", "model": "Corolla" }
];


Notice on our model that there multiple items with the same make, so our first step is to get a list of unique makes. This can be done by creating a hash table with the make property name as the key. We also add a checked property which can be bound (ngModel) to the checkbox to track what filters are selected.


ctrl.makes = {};

//build the list of makes using a hash
list.filter(function (value, index, arr) {
    if (!ctrl.makes[value.make]) {
        ctrl.makes[value.make] = { make: value.make, checked: true };
    }
});


Anonymous Function

The last step on the code is to build the filter logic. This can be done using an anonymous function which can be piped as a filter on the ngRepeat directive. The function gets each item on the collection via the item parameter. The item.make property is used as a key to get the object from the makes collection and validate if the item checked property is checked.  A true value means that the item meets the filter condition, and it is displayed.


ctrl.optionFilter = function () {
                    return function (item) {
                        return ctrl.makes[item.make].checked;
                    };
                };


Building the Views

We can now move forward with building our views. We need the checkboxes for the filter options as well as a grid for the inventory list. We can build those controls with the following steps:

Filter Options

We use our makes collection of objects to create the checkboxes using the ngRepeat directive. For the filter to work properly, we need to watch over the checked property by associating it to the ngModel directive.


<span class="center-block">
        <label data-ng-repeat="option in ctrl.makes">
            <input type="checkbox"
                   ng-model="option.checked"
                   ng-checked="option.checked"/> {{option.make}}  &nbsp;          
        </label>                  
    </span>     


Table / Grid

To build the grid, we use the ngRepeat directive on our list collection. If we look at the ngRepeat directive, we can see that we pipe the items to our anonymous function which is called for each item. This is needed  to check if the corresponding make is checked. We also alias the result, so we can display the count of items.


<table class="table table-bordered text-center">
    <tr ng-repeat=" item in ctrl.list | filter: ctrl.optionFilter() as result" >
        <td><i class="fa fa-car fa-2x text-primary">&nbsp;</i></td>            
        <td>{{item.year}}</td>
        <td>{{item.make}} </td>
        <td>{{item.model}}</td>             
    </tr>
</table>


In Action





Summary

We are able to see how to filter a list with multiple options using our old friend AngularJS filter and an anonymous function. This however is not an acceptable solution when using the new Angular generation of software as filters have been a major cause of performance issues when dealing with large datasets. We can learn more about that here Angular Documentation.  


In our next article, we see how to implement the same solution using Angular 5 with Typescript and Observers (Reactive Programming) which should address those performance concerns.

Check this article for the Angular, Typescript Reactive Version

Originally Published by ozkary.com


1/13/18

Mocking a REST API With Model First Development

When developing application that integrates with JSON APIs, we usually test the API calls with a development API Server. This is a great approach when such server is available. However, when we are also building the API or have no development backend available, we need to use a mock server API to enable our frontend and integration development to move forward.  In this article, we take a look at building a mock server with the Model First Development approach and json-server.

Model First Development

With Model First Development, we focus on developing the application models that are required for a successful integration. After we build the models, we can then focus on building the APIs for our basic CRUD operations.  This is where the use of json-server can help developers build mock servers by just using the defined models.

What is json-server?

Json-server is a Fake REST API server application built on Node.js that reads JSON models and creates basic CRUD operations on those models thus enabling the rapid creation of REST APIs. This is often used by front-end as well as integration developers to test the API calls with a mock server.
We should also note that json-server support other operations like sorting, filtering, paging, search among a few other features. For more information visit the home page at this location:


Installation

The setup for this application requires NPM as well as Node.js. Once those dependencies are installed, we can type the following command to install json-server.


npm install –g json-server


Building our Models

We are going to build a simple vehicle inventory with the year, make and model property names. In our models, we create two collections, makes and vehicles. We use these collections to illustrate how json-server creates different routes for each collection.


{
    "makes":["Nissan","Subaru","Toyota"],   
    "vehicles":[ 
        {"year":"2018","make":"Nissan","model":"Altima"},
        {"year":"2018","make":"Subaru","model":"Outback"},
        {"year":"2018","make":"Toyota","model":"4Runner"}   
    ]
}


The important thing to notice from our JSON sample is that we have included multiple collections in the same file. This is a requirement from json-server. One session of the json-server can only watch a single JSON file. To overcome this problem, we can start multiple sessions on different ports using a different file and port number.


json-server –watch ozkary-inventory.json –port 3005


Starting the Mock server

To start the mock server, we need to pass the –watch parameter with a target JSON file. In this example, we are running the command from the same directory where our JSON file is located.


json-server –watch ozkary-inventory.json


Once we execute this command, we should have a list of the resources (APIs) that are available from our mock server as well as the endpoint which defaults to port 3000.  This is the endpoint that we want to use for our API calls.




Testing the APIs

To quickly test our APIs, we can use Postman or a similar tool to test our GET, POST operations on our models.  When we use a GET operation, we can see the JSON data that comes back from our API. We can send a GET request with the ID parameter to simulate a search request for a specific record.

When we send a POST request, json-server simulates the creation of a new record and returns the id for that record. This is a good way to test out create, updates and delete operations without having to write lots of fake operations.



Summary


With the help of json-server, we are able to mock an API by first focusing on the application models. We then let the json-server handle the logic of the CRUD operations which are inferred by the model definition. This accelerates the front-end and integration efforts without having to implement a mock server.

Originally published by ozkary.com