2012-03-12 29 views
7

Có cách nào để tạo trường ko.computed được thông báo về các thay đổi xảy ra với các phần tử của mảng không?thay đổi theo dõi ko.com đã quy đổi của các phần tử của mảng

Suy nghĩ đầu tiên của tôi là sử dụng observableArray, nhưng nó đã không làm việc, bởi vì

An observableArray tracks which objects are in the array, not the state of those objects

Tuy nhiên, tôi đang đăng đoạn mã này để minh họa cho những gì tôi đang cố gắng để làm.

HTML:

<div data-bind="foreach:arr"> 
    <input type="text" value="" data-bind="value: a" /> 
</div> 

<div data-bind="foreach:arr"> 
    <p> 
     Field "a" is changed: <span data-bind="text: aChanged()? 'true': 'false'"></span> 
    </p> 
</div> 
<p> 
    Some "a" field from the array is changed: <span data-bind="text: someAChanged()? 'true': 'false'"></span> 
</p> 

JavaScript:

function AppViewModel() { 
    this.arr = ko.observableArray([new A(), new A()]); 
    this.someAChanged = ko.computed(function() { 
     var ch = false; 
     var arr = this.arr(); 
     for (var i = 0; i < arr.length; i ++) { 
      if (arr[i].aChanged()) { 
       ch = true; 
       break; 
      } 
      return ch; 
     } 
    }, this);  
} 

function A() { 
    this.a = ko.observable(1); 
    this.aChanged = ko.computed(function() { 
     return this.a() != 1; 
    }, this); 
} 

ko.applyBindings(new AppViewModel()); 

Như tôi không có quyền trả lời câu hỏi của riêng tôi, tôi gửi bài ý tưởng của tôi ở đây. Tôi quyết định sử dụng chức năng "đăng ký". Giải pháp của tôi là thêm liên kết "cha mẹ" vào các phần tử của một mảng. Bất cứ khi nào một lĩnh vực quan sát được thay đổi một lĩnh vực phụ thuộc vào cha mẹ trẻ em của nó bị thay đổi quá:

function Child() { 
    this._parent = null; 
    this.observableField = ko.observable(""); 
    this.observableField.subscribe(function (newVal) { 
     if (newVal... && this._parent) { 
      this._parent.anotherObservableField(...); 
     } 
    }); 
} 
Child.prototype._setParent(parent) {...} 

Trả lời

2

Bạn sẽ cần phải chắc chắn rằng someAChanged tính được đăng ký một sự phụ thuộc vào từng mục trong mảng của bạn.

Something như thế này nên làm việc:

function AppViewModel() { 
    this.arr = ko.observableArray([new A(), new A()]); 
    this.someAChanged = ko.computed(function() { 
     var ch = false; 
     var changedItem = null; 
     var arr = this.arr(); 

     ko.utils.arrayForEach(this.arr(), function(item){ 
      var changed = item.changed(); //someAChanged registers a change subscription here 

      if(changed && !ch){ 
       ch = true; 
       changedItem = item; 
      } 
     }); 

     return changedItem; 
    }, this);  
}; 

Về cơ bản này đăng ký một "thay đổi" thuê bao cho mỗi mục trong mảng của bạn. Mã trước đó của bạn đã dừng ở mã đầu tiên được tìm thấy, điều đó có nghĩa là không có mục nào khác trong mảng của bạn đã thêm đăng ký "thay đổi". Lặp qua từng mục trong mảng của bạn và làm cho nó phụ thuộc vào someAChanged được tính có thể của bạn sẽ tốn kém nếu bạn có nhiều mục trong mảng của mình.

Mã ở trên cũng sẽ trả lại mục đầu tiên đã thay đổi. Tôi cho rằng đây là những gì bạn muốn. Nếu không, nó sẽ được khá dễ dàng để làm việc lại nó để trở về một mảng các mặt hàng thay đổi.

+0

[Navneet Gupta] (http://stackoverflow.com/users/3846772/navneet-gupta) đăng này: "Làm thế nào để cho nó hoạt động nếu các mặt hàng mới được thêm vào observableArray Làm thế nào họ đã đăng ký? ? " –

+0

@ PeterO không phải là một vấn đề, khi tính toán gọi 'this.arr()', do đó, nó đăng ký vào mảng là tốt, sau đó trong cuộc gọi 'ko.utils.arrayForEach', sẽ đăng ký để' thay đổi' prop của mục mới được thêm vào. – Tyblitz

0

tôi đã làm nó thiết lập một giá trị ban đầu đơn giản trên tạo và kiểm tra xem có bất kỳ lĩnh vực tôi muốn kiểm nếu được thay đổi trên một quan sát được tính toán như thế này:

var initPrice = line.Price; 
    var initCurrency = line.IdCurrency; 

    self.isModified = ko.computed(function() { 
     return self.Price() !== initPrice || self.IdCurrency() !== initCurrency; 
    }); 
0

Bạn đã gần như ở đó tôi nghĩ. Html của bạn là tốt như là loại trực tiếp của bạn, nhưng chức năng tính toán someAChanged của bạn đã không hoạt động đúng. Nếu A đã thay đổi bạn đã đặt biến ch thành true và thoát khỏi vòng lặp for nhưng bạn không bao giờ thực sự trả về true. Trong thực tế, bạn không cần biến ch chút nào.

function AppViewModel() { 
    this.arr = ko.observableArray([new A(), new A()]); 
    this.someAChanged = ko.computed(function() { 
     var arr = this.arr(); 
     for (var i = 0; i < arr.length; i ++) { 
      if (arr[i]().aChanged()) { 
       return true; 
      } 
     } 
     return false; 
    }, this); 
} 
Các vấn đề liên quan