2016-05-13 72 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; 
    };