Rob Paddock
Rob Paddock

Reputation: 1003

Knockout JS Paging and Facet Search

I am trying to put together a single page application that allows faceted searching and paging at the same time. I am fairly new to Knockout and I am struggling getting the two concepts linked together.

The development site can be seen here http://especial2.egcommerce.com/search

function ProductDimensionsViewModel () {
    var self = this;

    self.dimensions = ko.observableArray();

    //self.dimensions(data);

    var baseUri = 'api/product_dimensions.php';
    $.getJSON(baseUri, self.dimensions);

    //self.dimensions.subscribe(function(updated) {
       // alert(updated);
   // });

    self.filterByBrand = ko.computed(function() {
        return ko.utils.arrayFilter(self.dimensions(), function(dimension) { return dimension.type == "BRAND"; })
    });

    self.filterByArea = ko.computed(function() {
        return ko.utils.arrayFilter(self.dimensions(), function(dimension) { return dimension.type == "AREA"; })
    });

    self.filterByType = ko.computed(function() {
        return ko.utils.arrayFilter(self.dimensions(), function(dimension) { return dimension.type == "TYPE"; })
    })

    self.filterByBrandMenu = ko.computed(function() {
        return ko.utils.arrayFilter(self.dimensions(), function(dimension) { return dimension.type == "BRAND" && dimension.menuItem == "YES"})
    });

    self.filterByAreaMenu = ko.computed(function() {
        return ko.utils.arrayFilter(self.dimensions(), function(dimension) { return dimension.type == "AREA" && dimension.menuItem == "YES"})
    });

    self.filterByTypeMenu = ko.computed(function() {
        return ko.utils.arrayFilter(self.dimensions(), function(dimension) { return dimension.type == "TYPE" && dimension.menuItem =="YES" })
    });



    self.products = ko.observableArray();
    $.getJSON("api/products", self.products);
    //self.products(product)

    //console.log(self.products(data.count));

    /*
     * Paging functionality
    */

    // only for example, used to demonstrate setting the total item count from a service call.
    self.SetTotalResults = ko.observable(100);

    // holds the total item count
    self.TotalResults = ko.observable();

    // actual pager, used to bind to the pager's template
    // first parameter must be an observable or function which returns the current 'total item count'.
    // it is wrapped in a ko.computed inside the pager.
    self.Pager = ko.pager(self.TotalResults);

    // Subscribe to current page changes.
    self.Pager().CurrentPage.subscribe(function () {
        self.search();
    });

    self.search = function () {
        // simulate a search

        // ie.:
        /*
         var maximumRows = self.Pager().PageSize(),
         searchText = self.SearchText(),
         startIndex = (self.Pager().CurrentPage() - 1) * maximumRows;
         myService.search(searchText, startIndex, maximumRows)
         .done(function(result) {
         // set your own results etc...
         self.TotalResults(result.totalItemCount);
         }
         */

        // setting 'total results'. This should be in your result callback
        // in this example we grab it from the form.
        var totalItemCount = self.SetTotalResults();
        self.TotalResults(totalItemCount);
    }

ko.applyBindings(new ProductDimensionsViewModel())

As you can see I have managed to populate the filters and pull in the products from a ajax call.

I now need some guidance with the following.

  1. How to filter the products based upon checkboxes on the left
  2. How to link the paging function to the product results.

Any help would be appreciated, the site is only ever likely to have 1500 products so i think the solution I am trying to put in place will make the navigating the products quite slick.

Thanks for any help Rob

Upvotes: 0

Views: 1248

Answers (1)

7zark7
7zark7

Reputation: 10145

This is a little challenging to explain without writing all the code, but hopefully these additions makes sense:

self.page = ko.observable(0)
self.pageSize = ko.observable(20)

self.filters = [
    { id: 'dining', label: 'Fine Dining', active: ko.observable(false) },
    { id: 'events', label: 'Hospitality and Events', active: ko.observable(false) },
    { id: 'restaurants', label: 'Restaurant', active: ko.observable(false) }
    // etc...
]

self.activeFilters = ko.computed(function() {
  return self.filters.filter(function(filter) {
    return filter.active();
  })
})
self.activeFilters.subscribe(function() {
    // Make ajax call based on activeFilters, and start and pageSize as params
})


<ul data-bind="foreach: filters">
  <li>
    <input type="checkbox" data-bind="checked: active">
    <label data-bind="text: label"></label>
  </li>
</ul>

The paging markup is not shown here, but would be bound to the self.page and self.pageSize observables depending on how you want to control it.

Hope this helps.

Upvotes: 1

Related Questions