📜 ⬆️ ⬇️

KnockoutJS: stateful list filtering



If you are good at KnockoutJS and JavaScript do not pass by! , we need your knowledge.

Beginner, do not miss. In the comments to this post will be tips on how to write on KnockoutJS .
')
Yes: filtering the list while maintaining the state of the filters in the cookie.
We are looking for: Best KnockoutJS practices, so as not to produce bad code.

Caution: I rarely write articles, because of which the design suffers. Do not be scared. Send errors and recommendations for registration in PM. Thank.

Screenshot






Source codes


Filter

<div class="filter-list"> <div class="filter"> <label for="filter_ended"><input type="checkbox" data-bind="checked: filterEnded" id="filter_ended" /> </label> </div> <div class="filter"> <label for="filter_simple"><input type="checkbox" data-bind="checked: isSimpleView" id="filter_simple"/>  </label> </div> <div class="filter"> <label for="filter_sort_date"><input type="radio" data-bind="checked: sorting" value="date" id="filter_sort_date" />   </label> </div> <div class="filter"> <label for="filter_sort_abc"><input type="radio" data-bind="checked: sorting" value="asc" id="filter_sort_abc" />  </label> </div> </div> 

data-bind="..." - Knockout binding to HTML.

 <input type="checkbox" data-bind="checked: filterEnded" id="filter_ended" /> 
- sets the checked attribute if filterEnded == true

 <input type="radio" data-bind="checked: sorting" value="date" id="filter_sort_date" /> 
- puts the checked attribute if sorting is equal to the value value attribute

View

 <div class="items" data-bind="foreach: filteredItems, css: {items_simple: isSimpleView}"> <div class="item" data-bind="text: name, css: {item_is_ended: is_ended}"></div> </div> 

filteredItems is an array storing filtered elements. All items are stored in viewModel.items .

foreach: filteredItems - walk through all elements of an array and apply a template to them inside .items .

css: {items_simple: isSimpleView} - adds the .items_simple class to .items if isSimpleView == true .

text: name - shows the text value of the name parameter (alternative to $data.name ) of the array element from filteredItems .

Data

 $items_json = json_encode( array( array( 'name' => '-', 'is_ended' => false, 'order_date' => 1 ), array( 'name' => '', 'is_ended' => false, 'order_date' => 2 ), array( 'name' => ' ', 'is_ended' => true, 'order_date' => 3 ), array( 'name' => 'GTO', 'is_ended' => true, 'order_date' => 4 ), )) 


JS plugin (before closing body )

 <script type="text/javascript" src="/assets/js/cookie.js"></script> <script type="text/javascript" src="/assets/js/libs/knockout-2.1.0.js"></script> <script type="text/javascript"> var data_items = <?= $items_json ?>; </script> <script type="text/javascript" src="/assets/js/filters.ko.js"></script> 


ViewModel ( filters.ko.js )

 (function () { //         false var getParamBool = function (paramName) { return !!((getCookie(paramName) === 'true')); }; //         defaultValue,     var getParam = function (paramName, defaultValue) { return getCookie(paramName) ? getCookie(paramName) : defaultValue; }; var viewModel = { items: ko.observableArray(data_items), // ,      filterEnded: ko.observable(getParamBool('filterEnded')), isSimpleView: ko.observable(getParamBool('isSimpleView')), sorting: ko.observable(getParam('sorting', 'date')), sortTypes: { //       'asc': function (left, right) { return left.name === right.name ? 0 : (left.name < right.name ? -1 : 1) }, 'date': function (left, right) { return left.order_date === right.order_date ? 0 : (left.order_date < right.order_date ? -1 : 1) } }, sortProcesssing: function (sortType) { //   sortType = sortType || this.sorting(); if (this.sortTypes[sortType]) { setCookie('sorting', sortType, 30); this.items.sort(this.sortTypes[sortType]); //  sort()    } } }; //   items  viewModel.filteredItems = ko.computed(function () { var onlyEnded = this.filterEnded(); if (onlyEnded) return ko.utils.arrayFilter(this.items(), function (item) { //  return item.is_ended == onlyEnded; }); else return this.items(); }, viewModel); //     ,     viewModel.sorting.subscribe(function (sortType) { viewModel.sortProcesssing(sortType); }); viewModel.filterEnded.subscribe(function (newValue) { setCookie('filterEnded', newValue, 30); }); viewModel.isSimpleView.subscribe(function (newValue) { setCookie('isSimpleView', newValue, 30); }); //       View viewModel.sortProcesssing(); ko.applyBindings(viewModel); //   })(); 


Materials on the topic




Masters, how to make the code even better?


UPD: code updated.
According to xdenser

On the advice of mac2000 and xdenser, parameters are given more logical names that better reflect their essence.

UPD2:
On the advice of porcelanosa and serjoga added explanations on the code.

Source: https://habr.com/ru/post/152847/


All Articles