Im trying to make Single Page Application (with Knockout.js - it's necessary to use it) which imitates products page in online shop. Here's how it looks like (for better understanding):
Im using require.js, knockout.js and underscore.js for filtering items by price. The problem is - sometimes im getting error that _.filter is not a function. Here's my Sidebar ViewModel file:
define(
['jquery', 'underscore', 'knockout', 'core/get_product_list', 'core/read_set_data', 'text!view-model/sidebar/sidebar.tmpl'],
function ($, _, ko, getProductList, ReadSetData, sidebarTemplate) {
var SidebarViewModel = function (options) {
//Variables
var self = this;
self.sidebarElement = options.sidebarElement;
self.currentProductsPerPage = ReadSetData.currentProductsPerPage;
self.pageNumber = ReadSetData.pageNumber;
self.items = ReadSetData.items();
self.itemsTotal = ko.computed(function () {
return self.items.length;
});
self.filterPrice = ko.observableArray();
//Applying template
self.sidebarElement.html(sidebarTemplate);
//Filtering by price using Underscore
self.applyPriceFilter = ko.computed(function(){
if (self.filterPrice().length !== 0) {
var minValue, maxValue;
$.each(self.filterPrice(), function() {
var min = Number(this.split('-')[0]),
max = Number(this.split('-')[1]);
if (!minValue && !maxValue) {
minValue = min;
maxValue = max;
}
if (minValue > min) minValue = min;
if (maxValue < max) maxValue = max;
});
var filterItems = _.filter(self.items, function(item) {
return (item.price() > minValue && item.price() < maxValue);
});
ReadSetData.pageNumber(0);
ReadSetData.items(filterItems);
}
else
{
ReadSetData.pageNumber(0);
ReadSetData.items(self.items);
}
});
};
return SidebarViewModel;
});
It's filtering by price as expected, but if i refresh page few times - im getting this error:
If i refresh a page again, this error dissapears and filtering working fine again. It seems like underscore.js doesn't loading and that's the reason of an error (as i think).
Here's my require.config:
require.config({
paths: {
text: '../libs/text/text',
jquery: '../libs/jquery/jquery-min',
popper: '../libs/popper/popper-min',
underscore: '../libs/underscore/underscore',
knockout: '../libs/knockout/knockout',
bootstrap: '../libs/bootstrap-grid/bootstrap',
material_design: '../libs/material-design/mdb'
},
shim: {
jquery: {
exports: '$'
},
underscore: {
exports: '_'
},
material_design: {
deps: ['jquery']
}
}
});
require(['jquery', 'popper', 'bootstrap', 'knockout', 'material_design', 'main'], function(
$,
popper,
bootstrap,
ko,
Material_design,
MainViewModel
) {
var mainContent = $('#main'); //keep a reference to the root element
// ---------------------------------------------
// Applying bind of the MainViewModel
// ---------------------------------------------
ko.applyBindings(
new MainViewModel({
element: mainContent
}),
mainContent[0]
);
});
What am i doing wrong? Maybe i wrote something in wrong order? Or any ideas what can be wrong? Thanks!