[ Please see updates at the bottom ]
I'm trying to make knockout depended selects, it's intended to make a "product" selection by these attributes, for example a product can have "size" and "material", if I selected "size", a knockout script make a request to the backend and retrieves which "material" available for the selected size, in other words, if an attribute is selected, other attributes are filtered out to show only available values ("all sizes": 1,2,3,4,5; "aluminium": 1,4).
Attributes list are completely dynamic, there are about 80 attributes which can be linked to the products in arbitrary way.
Are there any "best practices" for this situation?
I am trying to solve it with code like this, without success yet:
var ViewModel = function(data) {
var self = this;
self.data = data;
self.attributes = ko.observableArray();
self.data.forEach(function(item, i, a) {
// I passed .self to catch it later
// in products as view_model.attributes().
self.attributes.push(new VariableProduct(item, self));
})
};
var VariableProduct = function(item, view_model) {
var self = this;
self.attribute_name = ko.observable(item.name);
self.attribute_value = ko.observable('--');
// list of attribute values
self.attribute_values = ko.computed(function() {
var result = {};
view_model.attributes().forEach(function(attribute, i, a) {
// here I try to filter each attributes lists by values
// it doesn't work well
if (attribute.attribute_name() != self.attribute_name() && self.attribute_value() != '--') {
result = attribute.attribute_values().filter(
function(value) {
return value.indexOf(self.attribute_value()) >= 0;
});
}
});
return result;
});
};
UPDATE 1: With Dnyanesh's reference to ko.subscribe(), i've achived these results, isn't ok yet, but a progress:
http://jsfiddle.net/xwild/65eq14p3/
UPDATE 2: At the end it was solved with knockout.reactor and knockout.mapping plugins.
Related stackoverflow question with details and the answer.
To create an observable, assign the ko. observable function to the variable. A default value can be specified in the constructor of the call. Knockout then converts your variable into a function and tracks when the value changes, in order to notify the UI elements associated with the variable.
KO is able to create a two-way binding if you use value to link a form element to an Observable property, so that the changes between them are exchanged among them. If you refer a simple property on ViewModel, KO will set the form element's initial state to property value.
The $data variable is a built-in variable used to refer to the current object being bound. In the example this is the one of the elements in the viewModel.
Knockout's declarative binding system provides a concise and powerful way to link data to the UI. It's generally easy and obvious to bind to simple data properties or to use a single binding.
For dependent select I think you can use subscribe in following manner
var vm = {
sizes: ko.observableArray([
{ name: 'size 1', id: 1},
{ name: 'size 2', id: 2},
{ name: 'size 3', id: 3},
{ name: 'size 4', id: 4}
]),
selectedSize : ko.observable(0),
};
vm.selectedSize.subscribe(function(newValue){
alert('Selected Size is ---> ' + newValue )
// Here at this point call your ajax or backend method and bind the values which are coming form
});
ko.applyBindings(vm);
<script src="https://cdnjs.cloudflare.com/ajax/libs/knockout/3.0.0/knockout-min.js"></script>
<select data-bind="
options: sizes,
optionsText: 'name',
optionsValue: 'id',
value: selectedSize,
optionsCaption: 'Choose Size...'"">
</select>
<select data-bind="
options: material,
optionsText: 'name',
optionsValue: 'id',
value: selectedMaterial,
optionsCaption: 'Choose Material...'"">
</select>
I know I am talking about only part of solution to your problem but, I think you need to divide your data object to bind it to various controls.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With