Нокаут с привязкой, каскадное выпадающее меню, перезагрузка выбранных значений не работает

У меня есть нокаутирующий пример, использующий привязку «С» для создания каскадного раскрывающегося списка.

Раскрывающийся список работает нормально, если я выбираю значения, 4 раскрывающихся списка каскадируются с каждым соответствующим параметром выбора.

Однако я хотел бы сохранить настройку раскрывающегося списка, чтобы при загрузке страницы я мог вернуть сохраненные значения, точно так же, как предварительно установить значения.

Вывод значений, которые получают наблюдаемые, путем вызова «сохранить» после выбора из раскрывающегося списка. Но не работает при вызове loadPresetData для имитации отображения данных в наблюдаемые выбранные значения.

Я разветвил скрипку ниже. http://jsfiddle.net/turrytheman/3urLenmd/

var sampleModel=[{"products":[{"name":"1948 Porsche 356-A Roadster","year":[{"name":2015,"months":[{"name":"jan"},{"name":"april"},{"name":"dec"}]}]},{"name":"1948 Porsche Type 356 Roadster","year":[{"name":2014,"months":[{"name":"jan"},{"name":"april"},{"name":"dec"}]},{"name":2015,"months":[{"name":"oct"},{"name":"marc"},{"name":"feb"}]}]},{"name":"1949 Jaguar XK 120","year":[{"name":2019,"months":[{"name":"oct"},{"name":"jun"},{"name":"jul"}]},{"name":2013,"months":[{"name":"oct"},{"name":"marc"},{"name":"feb"}]}]}],"name":"Classic Cars"},{"products":[{"name":"1936 Harley Davidson El Knucklehead","year":[{"name":2011,"months":[{"name":"jan"},{"name":"nov"},{"name":"sep"}]}]},{"name":"1957 Vespa GS150","year":[{"name":2014,"months":[{"name":"jan"},{"name":"april"},{"name":"dec"}]},{"name":2015,"months":[{"name":"another"},{"name":"yet"},{"name":"another"}]}]}],"name":"Motorcycles"}];


var Cascading = function() {
    var self = this;
    self.category = ko.observable();
    self.product = ko.observable();
    self.years = ko.observable();
    self.month = ko.observable();

    // Whenever the category changes, reset the product selection
    self.category.subscribe(function(val) {
       self.product(undefined);
    });
    self.product.subscribe(function(val) {
       self.years(undefined);
    });
    self.years.subscribe(function(val) {
       self.month(undefined);
    });

    // Operations
    self.loadPresetData = function() { //simulating a load, recieved from AJAX, setting saved values
        self.category(JSON.parse('{"products":[{"name":"1936 Harley Davidson El Knucklehead","year":[{"name":2011,"months":[{"name":"jan"},{"name":"nov"},{"name":"sep"}]}]},{"name":"1957 Vespa GS150","year":[{"name":2014,"months":[{"name":"jan"},{"name":"april"},{"name":"dec"}]},{"name":2015,"months":[{"name":"another"},{"name":"yet"},{"name":"another"}]}]}],"name":"Motorcycles"}'));
        self.product(JSON.parse('{"name":"1936 Harley Davidson El Knucklehead","year":[{"name":2011,"months":[{"name":"jan"},{"name":"nov"},{"name":"sep"}]}]}'));
        self.years(JSON.parse('{"name":2015,"months":[{"name":"jan"},{"name":"april"},{"name":"dec"}]}'));
        self.month(JSON.parse('{"name":"april"}'));
}
    self.save = function() {
        var data = {"category": ko.toJSON(ko.toJS(self.category)),
                    "product": ko.toJSON(ko.toJS(self.product)),
                    "years": ko.toJSON(ko.toJS(self.years)) ,
                    "month": ko.toJSON(ko.toJS(self.month)) 
                    }
        console.log(data);
    };
};

ko.applyBindings(new Cascading());

HTML:

<div class='liveExample'> 
   <div>
       <select data-bind='options: sampleModel, optionsText: "name", optionsCaption: "Select...", value: category'> </select>
   </div>
   <div data-bind="with: category">
       <select data-bind='options: products, optionsText: "name", optionsCaption: "Select...", value: $parent.product'> </select>
   </div>
      <div data-bind="with: product">
       <select data-bind='options: year, optionsText: "name", optionsCaption: "Select...", value: $parent.years'> </select>
   </div>
      <div data-bind="with: years">
       <select data-bind='options: months, optionsText: "name", optionsCaption: "Select...", value: $parent.month'> </select>
   </div>
   <button data-bind='click: loadPresetData'>Load</button>
   <button data-bind='click: save'>Save</button>

    <div style="color: red"data-bind="text:'Category :' + ko.toJSON(category)"></div>
    <div style="color: green"data-bind="text:'Product :' + ko.toJSON(product)"></div>
    <div style="color: blue"data-bind="text:'Year :' + ko.toJSON(years)"></div>
    <div style="color: black"data-bind="text:'Months :' + ko.toJSON(month)"></div>
</div>

person fntstk    schedule 12.10.2017    source источник


Ответы (1)


Краткий ответ: раскрывающиеся списки не устанавливаются, потому что object, который вы устанавливаете на self.category(), и другие раскрывающиеся списки в loadPresetData не существуют в sampleModel (или sampleProductCategories в скрипке).

Да, есть объект, который выглядит и имеет те же свойства и вложенные массивы, что и объект, который создает JSON.parse(), но это совершенно другие объекты. Они не пройдут Strict Equality Comparison or "=== comparison". Вы можете проверить эту гипотезу, установив category и другие каскадные значения из самого массива sampleProductCategories.

self.loadPresetData = function() {
   self.category(sampleProductCategories[1]);
   self.product(sampleProductCategories[1].products[0]);
   self.years(sampleProductCategories[1].products[0].year[0]);
   self.month(sampleProductCategories[1].products[0].year[0].months[0]);
};

Теперь при обновлении category нокаут идет и ищет этот объект в sampleProductCategories. Он существует и, следовательно, category не будет установлен на undefined.

Вот обновленная скрипта

person adiga    schedule 12.10.2017
comment
Большое спасибо, это именно то, что я хотел. Я должен был подумать об этом подходе, но застрял, думая в одну сторону... Отличный ответ, короткий и лаконичный. - person fntstk; 13.10.2017