From 86e4590069e0c4ce9492928dabc2e7e6a3dc5214 Mon Sep 17 00:00:00 2001 From: NikolayAlipiev Date: Thu, 6 Dec 2018 17:47:56 +0200 Subject: [PATCH] fix(combo knockout): update ds when new ds length is the same #1852 --- ...fragistics.ui.combo.knockout-extensions.js | 85 ++++++++++--------- tests/unit/knockout/combo/combo-test.js | 14 +++ 2 files changed, 61 insertions(+), 38 deletions(-) diff --git a/src/js/extensions/infragistics.ui.combo.knockout-extensions.js b/src/js/extensions/infragistics.ui.combo.knockout-extensions.js index f9968e248..56cdccb4a 100644 --- a/src/js/extensions/infragistics.ui.combo.knockout-extensions.js +++ b/src/js/extensions/infragistics.ui.combo.knockout-extensions.js @@ -55,6 +55,49 @@ } } + function applyListItemsBindings(valueAccessor) { + var combo = valueAccessor().combo, + $comboList = combo.igCombo("listItems"), + options = valueAccessor().options, + dataSource = ko.utils.unwrapObservable(valueAccessor().dataSource), + i; + if (dataSource) { + for (i = 0; i < dataSource.length; i++) { + if (ko.isObservable(dataSource[ i ])) { + ko.applyBindingsToNode($comboList[ i ], { + igComboItem: { + combo: combo, + value: dataSource[ i ], + index: i, + options: options + } + }, dataSource[ i ]); + } + } + } + } + + function isNewDataSource(valueAccessor) { + var combo = $(valueAccessor().combo), + listLength = combo.igCombo("listItems").length, + valueKey = combo.igCombo("option", "valueKey"), + viewModelDataSource = ko.utils.unwrapObservable(valueAccessor().dataSource), + comboDataSource = ko.utils.unwrapObservable(combo.igCombo("option", "dataSource").data()), + index; + if (listLength === viewModelDataSource.length && valueKey !== undefined) { + comboDataSource = + ko.utils.unwrapObservable(combo.igCombo("option", "dataSource").data()); + for (index = 0; index < comboDataSource.length; index++) { + if (comboDataSource[ index ][ valueKey ] !== + viewModelDataSource[ index ][ valueKey ]) { + return true; + } + } + return false; + } + return true; + } + ko.bindingHandlers.igCombo = { init: function (element, valueAccessor) { var combo = $(element), @@ -148,26 +191,7 @@ ko.bindingHandlers.igComboList = { init: function (element, valueAccessor) { - var combo = valueAccessor().combo, - $comboList = combo.igCombo("listItems"), - options = valueAccessor().options, - dataSource = ko.utils.unwrapObservable(valueAccessor().dataSource), - i; - - if (dataSource) { - for (i = 0; i < dataSource.length; i++) { - if (ko.isObservable(dataSource[ i ])) { - ko.applyBindingsToNode($comboList[ i ], { - igComboItem: { - combo: combo, - value: dataSource[ i ], - index: i, - options: options - } - }, dataSource[ i ]); - } - } - } + applyListItemsBindings(valueAccessor); }, update: function (element, valueAccessor) { var combo = $(valueAccessor().combo), @@ -175,26 +199,11 @@ options = valueAccessor().options, dataSource = ko.utils.unwrapObservable(valueAccessor().dataSource), dropDownScroller = combo.data("igCombo")._options.$dropDownScrollCont, - lastScrollTop = dropDownScroller ? dropDownScroller.scrollTop() : 0, - $comboList, i; + lastScrollTop = dropDownScroller ? dropDownScroller.scrollTop() : 0; - if (listLength !== dataSource.length) { + if (isNewDataSource(valueAccessor)) { combo.one("igcomboitemsrendered", function () { - $comboList = combo.igCombo("listItems"); - if (dataSource) { - for (i = 0; i < dataSource.length; i++) { - if (ko.isObservable(dataSource[ i ])) { - ko.applyBindingsToNode($comboList[ i ], { - igComboItem: { - combo: combo, - value: dataSource[ i ], - index: i, - options: options - } - }, dataSource[ i ]); - } - } - } + applyListItemsBindings(valueAccessor); selectItems(combo, valueAccessor().selectedItems); }); diff --git a/tests/unit/knockout/combo/combo-test.js b/tests/unit/knockout/combo/combo-test.js index f2aece564..080cda60b 100644 --- a/tests/unit/knockout/combo/combo-test.js +++ b/tests/unit/knockout/combo/combo-test.js @@ -55,6 +55,8 @@ QUnit.module("Knockout unit tests for igComboEditor", { this.nameList = ko.observableArray(tmp); this.selectedItemsValue = ko.observableArray(["value2"]); this.selectedItemsWhole = ko.observableArray([{ name: "name2", value: "value2" }]); + + this.oneItemData = ko.observable([{id: 0, name: 'Item 0'}]); }, applyBindings: function () { ko.applyBindings(this.model, this.qunitFixture[0]); @@ -452,6 +454,18 @@ QUnit.test("[ID13] Combo editor test big data", function (assert) { assert.ok(end - start < 5000, "Binding big data should take less than 5 seconds"); }); +QUnit.test('Changing data source with data source with the same length but different items', function (assert) { + assert.expect(1); + var comboCont = $(this.divTag).appendTo(this.qunitFixture); + + comboCont.append($("").attr("data-bind", "igCombo: { dataSource: oneItemData, textKey: 'name', valueKey: 'id', width: '200', mode: 'dropdown', enableClearButton: false }")).appendTo(".test-container"); + ko.cleanNode(comboCont[0]); + ko.applyBindings(this.model, comboCont[0]); + this.model.oneItemData([{id: 6, name: "Item 6"}]); + assert.equal($("#combo").igCombo("option", "dataSource").data()[0].id, 6, "data source not updated"); + comboCont.remove(); +}); +