2012-12-01

Paged Grid with Knockout.js and WebApi

,
I want to see how easily you can create a custom grid that uses an WebApi as datasource and that allows the user to page the data and also allow them to choose a page size for the grid.

The WebApi

The WebApi will return a viewmodel that contains an array of names (string) and a property that specifies how many pages that there are available.
    public class NamesGridViewModel
    {
        public IEnumerable<String> Names { get; set; }

        public int NumberOfPages { get; set; }
    }

The WebApi itself will contain a method that accepts 2 parameters. The parameters will be page (the page that we request) and pagesize (how many entries a page contains). This method will be responsible for calculating how many pages there are and to serve the requested names based on the 2 parametes.
    public class ValuesController : ApiController
    {
        public IList<String> Names
        {
            get { return new List<String> { "Fred", "Barney", "Betty", "Wilma", "Bart", "Lisa", "Maggie", "Homer", "Marge" }; }
        }
            
        public NamesGridViewModel Get(int page, int pagesize)
        {
            return new NamesGridViewModel
                       {
                           // get the request names for the specific page
                           Names = (0 == page? null : Names.Skip((page - 1)*pagesize).Take(pagesize).ToArray())
                           ,
                           // calculated number of pages and ceil the value
                           NumberOfPages = ((int) Math.Ceiling((double) Names.Count/pagesize))
                       };
        }
    }

The client


The client will need a reference to kockout.js. With knockout.js it is possible to apply the MVVM pattern and also work with templates in javascript.


The UI

Page size: <select data-bind="options: availablePageSize, optionsText: $data, value: selectedPageSize"></select><!-- the grid --><table data-bind="with: namesGridViewModel">
    <thead>
        <tr>
            <th>
                Name
            </th>
        </tr>
    </thead>
    <tbody data-bind="foreach: Names">
        <tr>
            <td data-bind="text: $data">
            </td>
        </tr>
    </tbody>
</table><!--Contains the page links--><div id="pager"></div>

The Javascript

<script type="text/javascript">
    // Our  ViewModel.
    function pageViewModel() {
        var self = this;
        self.namesGridViewModel = ko.observable(); // contains the viewmodel returned by the WebApi
        self.selectedPageSize = ko.observable(3); // contains the selected page size, default value is 3
        self.availablePageSize = ko.observableArray([1, 2, 3, 4, 5]); // contains the available page sizes a user can select
        self.selectedPage = ko.observable(1); // contains the selected page

        // Add a click event to all future element with a class "pageIndex". This event will fire
        // when the user clicks a specific page.
        $("#pager").on("click", ".pageIndex", function (event) {
            // set the selected page in the viewModel
            self.selectedPage($(this).text());
        });

        // This function will be used to get the data from our WebApi. The requested page and page size are passed
        // as a parameter. The result will be stored in the namesGridViewModel property. This will cause that the subscribe event
        // for the namesGridViewModel will be fired ==> the page links will be created.
        self.navigate = function () {
            $.get("/api/values?page=" + self.selectedPage() + "&pagesize=" + self.selectedPageSize(), self.namesGridViewModel);
        };

        // Function that will subscribe to all the needed events.
        self.SubscribeToEvents = function () {

            // This event will fire when selectedPageSize is changed.
            self.selectedPageSize.subscribe(function (newValue) {
                self.selectedPage(1);
                self.navigate();
            });

            // This event will be fired when the selectedPage is changed.
            self.selectedPage.subscribe(function (newValue) {
                self.navigate();
            });

            // This event will fire when a new value is defined for the namesGridViewModel.
            // It will create the page links below the grid.
            self.namesGridViewModel.subscribe(function (newValue) {
                var numberOfPages = newValue.NumberOfPages;
                var $pager = $("#pager");
                // clear the pager
                $pager.html("");
                // created the pages the user can click on
                for (var i = 1; i <= numberOfPages; i++) {
                    var link = $('<a class="pageIndex">' + i + '</a>');
                    $pager.append(link);
                }
            }, this);
        };
        
        // This function will be used to kick start everything.
        self.bind = function () {
            self.SubscribeToEvents();
            self.navigate();
            ko.applyBindings(self);
        }
    }
    // Create the viewModel and bind it.
    $(function () { new pageViewModel().bind(); })</script>

The result


image

Summary


You have seen how to create a basic paging grid using Knockout.js.You can easily extend this example to also allow sorting. The solution can be downloaded here.

15 comments:

  1. Nice example! Thanks!

    ReplyDelete
  2. I need a more complex observable data (in your code is an array of string, "Names").

    same as :
    var ObservableProduct = function (productCode, productdescription, imageName) {
    this.ProductCode = ko.observable(productCode);
    this.ProductDescription = ko.observable(productdescription);
    this.ImageName = ko.observable(imageName);
    };
    With computed data, etc...

    but I was not able to modify your code to get the result, you can give me a hand?

    ReplyDelete
  3. Nice article Thanks :)

    ReplyDelete
  4. Nice articles Thanks a lot

    ReplyDelete
  5. I have some confusion with the codes that were used here and I guess you need to edit some of it. But anyhow, this post is commendable for a dissertation writing topic.

    ReplyDelete
  6. Wow! Thank you! I continually needed to write on my site something like that. Can I take a fragment of your post to my blog.create free store cards

    ReplyDelete
  7. articles that I really like and thank you for this excellent article
    togel online

    ReplyDelete
  8. Online Casino and online slot games is a way to be at the casino every single day from the luxury and comfort of your own home or anywhere else! scr888 apk is the best way to play online casino and slot games platform with unlimited options and endless scr888 apk possibilities. All the best of and popular casino and slot games can be played online by scr888 apk such as poker, bingo, free slots and a lot more! Live dealers, no deposits and unlimited access to scr888 apk … what more could one ask for! We guarantee a good and quality online casino experience and entertainment like never before! We offer numerous scr888 apk promotions and bonuses to all our customers! We guarantee a great time, every time! We have a pool of happy and satisfied customers who keep coming back to us for more and more entertainment with just a one click of scr888 apk . We pride in calling ourselves the best online casino and slot games platform as we offer a huge variety of scr888 apk and have a wide network of quality promotions and happy customers. Free slot games, an easy to win jackpot possibility and the best graphic slot games… We offer and guarantee scr888 apk all and more!

    Going to the casino has been a fascinating experience for several years, all over the world. Casinos promise unlimited fun, excitement and thrill! Unfortunately, there aren’t too many good Malaysia Casino that can promise the excitement one is looking for! Also, going to a casino is an expensive affair and can really burn a hole in one’s pocket by scr888 apk !

    ReplyDelete
  9. Valuable site, where did u come up with the 918kiss malaysia information in this posting? I am pleased I discovered it though, ill be checking back soon to find out what new content pieces u have.

    ReplyDelete
  10. Subsequently, after 918Kiss Malaysia spending many hours on the internet at last We've uncovered an individual that definitely does know what they are discussing many thanks a great deal wonderful post.

    ReplyDelete
  11. Regards Admin, good information is very useful. Continue on with insightful articles like this.
    We are from the Trusted Jud1 Onl1ne Visitorbet Game. Do not be refreshed to join us.
    Agen Slot Games
    Agen Casino Online
    Agen Bola Terpercaya
    Bandar Bola
    Agen Poker Terpercaya
    Agen Poker Online
    Thank A lot

    ReplyDelete
  12. JSON Formatter online tool to minify, beautify your json

    ReplyDelete
  13. Hii

    Thank you for the informative article. Wow! I've always wanted to create content on my website similar to that. Here is sharing some Microsoft Azure DevOps Solutions (AZ-400) information may be its helpful to you.

    Microsoft Azure DevOps Solutions (AZ-400)

    ReplyDelete