Filter Data By Letters In Data Using Knockoutjs in ASP.Net Application

Introduction

In my previous article I explained How to Filter Data By a Set of Strings Using Knockoutjs in ASP.NET Application.

This article explains how to filter data by the letters in data using Knockoutjs in an ASP.NET Application.

At the end of the article you will get output that will look like this:

filter alphabet knockout1.jpg

Let's see the procedure to create the application.

Step 1

First of all we will work on the View Model of our application. Write this code in the ViewModel of your application.

        <script>

            function Item(name, category, price) {

                this.name = ko.observable(name);

                this.category = ko.observable(category);

                this.price = ko.observable(price);

                this.priceWithTax = ko.dependentObservable(function () {

                    return (this.price() * 1.05).toFixed(2);

                }, this);

            }

 

            var viewModel = {

                categories: ["Burger", "Drinks", "Pizza", "Non-Veg"],

                items: ko.observableArray([]),

                filter: ko.observable(""),

                search: ko.observable(""),

                addItem: function () {

                    this.items.push(new Item("New", "", 1));

                },

                removeItem: function (item) {

                    this.items.remove(item);

                }

            };

 

            viewModel.filteredItems = ko.dependentObservable(function () {

                var filter = this.filter().toLowerCase();

                if (!filter) {

                    return this.items();

                } else {

                    return ko.utils.arrayFilter(this.items(), function (item) {

                        return ko.utils.stringStartsWith(item.name().toLowerCase(), filter);

                    });

                }

            }, viewModel);

 

            viewModel.total = ko.dependentObservable(function () {

                var total = 0;

                ko.utils.arrayForEach(this.filteredItems(), function (item) {

                    var value = parseFloat(item.priceWithTax());

                    if (!isNaN(value)) {

                        total += value;

                    }

                });

                return total.toFixed(2);

            }, viewModel);

 

            viewModel.firstMatch = ko.dependentObservable(function () {

                var search = this.search().toLowerCase();

                if (!search) {

                    return null;

                } else {

                    return ko.utils.arrayFirst(this.filteredItems(), function (item) {

                        return ko.utils.stringStartsWith(item.name().toLowerCase(), search);

                    });

                }

            }, viewModel);

 

            viewModel.mappedItems = ko.dependentObservable(function () {

                var items = ko.toJS(this.items);

                return ko.utils.arrayMap(items, function (item) {

                    delete item.priceWithTax;

                    return item;

                });

            }, viewModel);

 

            var JSONdataFromServer = '[{"name":"McVegi","category":"Burger","price":25},{"name":"Pepsi","category":"Drinks","price":25},{"name":"McGrilledChicken","category":"Non-Veg","price":35},{"name":"FarmHouse","category":"Pizza","price":270}]';

 

            var dataFromServer = ko.utils.parseJson(JSONdataFromServer);

 

            var mappedData = ko.utils.arrayMap(dataFromServer, function (item) {

                return new Item(item.name, item.category, item.price);

            });

 

            viewModel.items(mappedData);

 

            ko.applyBindings(viewModel);

        </script>

Here first I created a function named Item. In this function I passed a few Observables named named, category and price, a dependent Observable is also declared named priceWithTax. This dependent observable is dependent on the price Observable since it will calculate the the price of an item after adding the tax to it's price.

After that in ViewModel function again a few Observables and an Observable Array is declared. The Observable Array is declared as the items and the Observables are named filter and search. After that two functions are created named AddItem and RemoveItems, these functions will be used by the user to add a new item in the Observable Array and to remove an item from the Observable Array.

Then a function is created named filteredItems. This function will be used to filter the items as the user enters letters, it will filter the data in the same manner whether the user enters the letters in capitalized or uncapitalized.

After that a function is created that will help to find the total of items in both the cases whether they all are available or they are filtered.

Next is a function named firstMatch. This function will highlight the first row of data that matches the letters entered.

After that the mapping of the data is done and also a few static data items are also passed that will be seen by the user on running the application.

Now our work on the View Model is complete. Our next step will be to work on the View of our application.

Step 2

Now we will work on the View of our application. Write this code in the View of your application:

    <div>

<table id="mytable" data-bind="triggerUpdate: items">

    <thead>

        <tr>

            <th>Name</th>

            <th>Category</th>

            <th>Price</th>

            <th>w/Tax</th>

            <th></th>

        </tr>

    </thead>

    <tbody data-bind="template: { name: 'itemsTmpl', foreach: filteredItems }"></tbody>

    <script id="itemsTmpl" type="text/html">

        <tr data-bind="css: { matched: $data === $root.firstMatch() }">

            <td>

                <input data-bind="value: name" />

            </td>

            <td>

                <select data-bind="options: $root.categories, value: category"></select>

            </td>

            <td>

                <input class="n" data-bind="value: price" />

            </td>

            <td class="n" data-bind="text: priceWithTax">

            </td>

            <td>

                <a href="#" data-bind="click: $root.removeItem.bind($root)">Delete</a>

            </td>

        </tr>

    </script>

    <tr>

        <td>

            <a href="#" data-bind="click: addItem">Add Item</a>

        </td>

        <td></td>

        <td class="n">Total: </td>

        <td class="n" data-bind="text: total"></td>

        <td></td>

    </tr>

</table>

 

<h3>Filter display by name</h3>

<p>Filter: <input data-bind="value: filter, valueUpdate: 'afterkeydown'" /></p>

 

<h3>Find first match by name</h3>

<p>Search: <input data-bind="value: search, valueUpdate: 'afterkeydown'" /></p>

<hr />

    </div>

Here first the Table is bound with the items, then a tbody is bound with the filteredItems that is an array, the <tr> is bound with the firstMatch which means that it will highlight the row that is the first of the matching letters provided by the user at run time.

After that a TextBox is created that is bound with the name, then a drop down is created that is bound with the categories, this will allow the user to select a category from the available options.

After that again a TextBox is created that is bound with the price of items. After that the price of an item along with its tax is shown.

 In the next two <td> items a link button is provided that when clicked will delete and add a row.

After the table an input box is provided, when the user will enter any letters in this input box then it will filter the data depending on the letters provided in this input box.

Towards the end another input box is created, this input box will help to highlight the row that is the first matching of the letters provided by the user.

Now your application is completed and is ready to run.

Output

On running the application you will get output like this:

filter alphabet knockout1.jpg

Now if I enter any letters in the first TextBox then you will see that the data available in the grid format and is filtered depending on the Letters. Even if I am providing the letters uncapitalized then it will also filter the data having the capital letter as starting letters.

filter alphabet knockout2.jpg

You can see that the price of all the items are automatically provided with the Tax added and their subtotal is also provided at the end.

Now I am providing the value in the second TextBox also and you will see that it will highlight the row that is the first with the data of those letters.

filter alphabet knockout3.jpg