Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

knockout.js dependent variable selects

[ 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.

like image 888
xwild Avatar asked Mar 16 '15 11:03

xwild


People also ask

How do I assign a value to knockout observable?

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.

What is two way data binding in knockout JS?

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.

What is $data in knockout?

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.

What is data bind in knockout JS?

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.


1 Answers

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.

like image 77
Dnyanesh Avatar answered Nov 15 '22 08:11

Dnyanesh