2016-05-13 74 views
0

我想修改我的底層數據對象並獲取頁面上的能夠更新並顯示新列。數據對象更新正常,但不會觸發UI的重新呈現。KnockoutJS - 當屬性添加到對象時添加列

我有什麼不明白的?

http://jsfiddle.net/Xpx7f/198/

<table> 
    <thead> 
     <tr data-bind="foreach: columnNames"> 
      <th> <span data-bind="text: $data"></span> 

      </th> 
     </tr> 
    </thead> 
    <tbody data-bind="foreach: items"> 
     <tr data-bind="foreach: $parent.columnNames"> 
      <td><input data-bind="value: $parent[$data]"></td> 
     </tr> 
    </tbody> 
</table> 

和JavaScript:

var vm; 

window.onload = function() { 
var VM = function() { 
    var self = this; 
    self.items = ko.observableArray(); 
    self.columnNames = ko.computed(function() { 
     if (self.items().length === 0) 
      return []; 
     var props = []; 
     var obj = self.items()[0]; 
     for (var name in obj) 
      props.push(name); 
     return props; 


    }); 

}; 
vm = new VM(); 

ko.applyBindings(vm); 

vm.items.push({ 
    'Name': 'John', 
    'Age': 25 
}); 
vm.items.push({ 
    'Name': 'Morgan', 
    'Age': 26 
}); 

// Add an extra property to each object 
for (var i = 0; i < vm.items().length; i++) { 
     vm.items()[i].Weight = '50kg'; 
} 
// ????? Table should update with new column 'Weight' 

} 
+0

有可觀察到的數組中沒有「新」的項目,所以它不會觸發可觀察的事件。您可以嘗試手動觸發更新。 – user3297291

回答

0

你沒有真正更新觀察到的,但添加一個新的領域對象包含。

在將一些屬性追加到KO數組內的對象後,嘗試使用vm.items.valueHasMutated();

var vm; 
 

 
window.onload = function() { 
 
    var VM = function() { 
 
    var self = this; 
 
    self.items = ko.observableArray(); 
 
    self.columnNames = ko.computed(function() { 
 
     if (self.items().length === 0) 
 
     return []; 
 
     var props = []; 
 
     var obj = self.items()[0]; 
 
     for (var name in obj) 
 
     props.push(name); 
 
     return props; 
 

 

 
    }); 
 

 
    }; 
 
    vm = new VM(); 
 

 
    ko.applyBindings(vm); 
 

 
    vm.items.push({ 
 
    'Name': 'John', 
 
    'Age': 25 
 
    }); 
 
    vm.items.push({ 
 
    'Name': 'Morgan', 
 
    'Age': 26 
 
    }); 
 

 
    for (var i = 0; i < vm.items().length; i++) { 
 
    vm.items()[i].Weight = '50kg'; 
 
    } 
 
    vm.items.valueHasMutated(); 
 

 
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/knockout/3.2.0/knockout-min.js"></script> 
 
<table> 
 
    <thead> 
 
    <tr data-bind="foreach: columnNames"> 
 
     <th> <span data-bind="text: $data"></span> 
 

 
     </th> 
 
    </tr> 
 
    </thead> 
 
    <tbody data-bind="foreach: items"> 
 
    <tr data-bind="foreach: $parent.columnNames"> 
 
     <td> 
 
     <input data-bind="value: $parent[$data]"> 
 
     </td> 
 
    </tr> 
 
    </tbody> 
 
</table>

你在做什麼在這裏基本上是告訴觀察到的陣列,該值已更改,所有用戶將被告知一次

如果你看看淘汰賽觀察到陣推的實現,你可以看到,每一個推,同樣的邏輯也適用 - 他們稱之爲valueHasMutated()

ko.observableArray['fn']['push'] = function() { 
     // Use "peek" to avoid creating a subscription in any computed that we're executing in the context of 
     // (for consistency with mutating regular observables) 
     var underlyingArray = this.peek(); 
     this.valueWillMutate(); 
     this.cacheDiffForKnownOperation(underlyingArray, methodName, arguments); 
     var methodCallResult = underlyingArray[methodName].apply(underlyingArray, arguments); 
     this.valueHasMutated(); 
     // The native sort and reverse methods return a reference to the array, but it makes more sense to return the observable array instead. 
     return methodCallResult === underlyingArray ? this : methodCallResult; 
    };