2013-05-02 29 views
5

Tôi cần chỉnh sửa một mảng các số nguyên trong một ứng dụng web, sử dụng Javascript và Knockout.js. Mảng này sẽ bị ràng buộc vào các hộp văn bản, và bất cứ khi nào giá trị của bất kỳ hộp văn bản nào được thay đổi, mảng được cập nhật. Và khi nó được cập nhật, tổng các phần tử được tính toán.Thay đổi theo dõi - phần tử quan sát được trong observableArray

Đây là lần thử đầu tiên của tôi: http://jsfiddle.net/ZLs2A/0/. Nó không hoạt động (giá trị tổng không cập nhật khi gõ một giá trị mới cho bất kỳ phần tử nào). Đó là khi tôi nhận ra observableArray sẽ chỉ kích hoạt hàm tổng sau khi chèn hoặc xóa các mục.

<h4>Numbers</h4> 
<button data-bind="click: add">Add</button> 
<ul data-bind="foreach: numbers"> 
    <li> 
     <input data-bind="value: $data"></input> 
    </li> 
</ul> 
<span data-bind="text: sum"></span> 

function MyViewModel() { 
    var self = this; 

    self.numbers = ko.observableArray([ 
     1, 
     2, 
     3 
    ]); 

    self.sum = ko.computed(function() { 
     var items = self.numbers(); 
     var total = 0; 
     for (var i = 0; i < items.length; i++) { 
      total += parseInt(items[i]); 
     } 
     return total; 
    }); 

    self.add = function() { 
     var lastIndex = self.numbers().length - 1; 
     var lastValue = self.numbers()[lastIndex]; 
     self.numbers.push(lastValue + 1); 
    } 
} 

ko.applyBindings(new MyViewModel()); 

Cố gắng tiếp theo của tôi là làm cho mọi thành phần trong dãy số có thể quan sát được (http://jsfiddle.net/ZLs2A/1/). Nó không hoạt động trở lại.

self.numbers = ko.observableArray([ 
    ko.observable(1), 
    ko.observable(2), 
    ko.observable(3) 
]); 

Thử cuối cùng của tôi là tạo một lớp mới (ArrayItem) để giữ giá trị của phần tử bên trong một thuộc tính quan sát được. Lần này nó hoạt động! (http://jsfiddle.net/ZLs2A/3/)

<h4>Numbers</h4> 
<button data-bind="click: add">Add</button> 
<ul data-bind="foreach: numbers"> 
    <li> 
     <input data-bind="value: value"></input> 
    </li> 
</ul> 
<span data-bind="text: sum"></span> 

function MyViewModel() { 
    var self = this; 

    self.numbers = ko.observableArray([ 
     new ArrayItem(1), 
     new ArrayItem(2), 
     new ArrayItem(3) 
    ]); 

    self.sum = ko.computed(function() { 
     var items = self.numbers(); 
     var total = 0; 
     for (var i = 0; i < items.length; i++) { 
      total += parseInt(items[i].value()); 
     } 
     return total; 
    }); 

    self.add = function() { 
     var lastIndex = self.numbers().length - 1; 
     var lastItem = self.numbers()[lastIndex]; 
     var newValue = parseInt(lastItem.value()) + 1; 
     self.numbers.push(new ArrayItem(newValue)); 
    } 
} 

function ArrayItem(value){ 
    var self = this; 
    self.value = ko.observable(value); 
} 

ko.applyBindings(new MyViewModel()); 

Tuy nhiên, tôi không muốn tạo lớp ArrayItem mới này. Có cách nào để loại bỏ nó, làm cho ví dụ làm việc chỉ có một observableArray của các yếu tố quan sát (như nỗ lực thứ hai của tôi)?

+2

Tác giả của KO trả lời [này (? Có thể lặp lại) câu hỏi] (http://stackoverflow.com/questions/9510539/knockout-js-how-to-correctly-bind-an -observablearray), về cơ bản theo cách tương tự với phiên bản cuối cùng của bạn với một hàm tạo 'ArrayItem' (anh ta chỉ nhấn mạnh hàm đó). Câu trả lời là một năm cũ, vì vậy một cái gì đó có thể đã thay đổi trong thời gian có nghĩa là ... Nếu nó không có, nó có vẻ như bạn đã trả lời câu hỏi của riêng bạn. – Jeroen

+0

Có lẽ đáng nhắc đến việc tích hợp Breeze.js với Knockout.js, điều này bổ sung thêm tính năng Theo dõi Thay đổi trong số những thứ khác. http://www.breezejs.com/ –

Trả lời

2

Loại bỏ sẽ không theo dõi giá trị, nhưng dưới dạng giải pháp thay thế, bạn có thể sử dụng sự kiện tự động nhấn hoặc thay đổi và cập nhật giá trị. Xem fiddle: http://jsfiddle.net/tkirda/ZLs2A/4/

function MyViewModel() { 
    var self = this; 

    self.numbers = ko.observableArray([ 
     1, 
     2, 
     3 
    ]); 

    self.onChange = function(val, e){ 
     var el = e.srcElement; 
     var newVal = parseInt(el.value); 
     var index = parseInt(el.getAttribute('data-index')); 
     self.numbers()[index] = newVal; 
     self.updateSum(); 
    } 

    self.sum = ko.observable(0); 

    self.updateSum = function() { 
     var items = self.numbers(); 
     var total = 0; 
     for (var i = 0; i < items.length; i++) { 
      total += parseInt(items[i]); 
     } 
     self.sum(total); 
    }; 

    self.updateSum(); 

    self.add = function() { 
     var lastIndex = self.numbers().length - 1; 
     var lastValue = self.numbers()[lastIndex]; 
     self.numbers.push(lastValue + 1); 
    } 
} 

ko.applyBindings(new MyViewModel()); 
+0

Mặc dù điều này dường như hoạt động với IE11, tổng trong ví dụ jsfiddle không cập nhật về các thay đổi của các giá trị trong trường văn bản trong Firefox 45.0.1 – Stefan

Các vấn đề liên quan