2012-12-21 10 views
9

Tôi có 3 biến quan sát được trong dạng xem và muốn xuất ra giá trị được định dạng. Tuy nhiên, tôi không muốn viết phương pháp tính toán cho mỗi người trong số họ vì chúng giống hệt nhau. Cách tốt nhất để sử dụng lại mã là gì? Cảm ơn.Tạo một quan sát được tính toán cho các giá trị được định dạng cho một loạt các biến

Mã Tôi sẽ đạt được là:

this.formattedPrice = ko.computed({ 
     read: function() { 
      return '$' + this.price().toFixed(2); 
     }, 
     write: function (value) { 
      // Strip out unwanted characters, parse as float, then write the raw data back to the underlying "price" observable 
      value = parseFloat(value.replace(/[^\.\d]/g, "")); 
      this.price(isNaN(value) ? 0 : value); // Write to underlying storage 
     }, 
     owner: this 
    }); 

Và ví dụ thất bại là ở: Jsfiddle

Cảm ơn,

Trả lời

17

Dưới đây là một vài cách mà bạn có thể thực hiện tái sử dụng này.

Nếu bạn muốn xử lý điều này trong mô hình chế độ xem của mình, thì lựa chọn tốt là tạo tiện ích mở rộng sẽ lưu trữ định dạng được tính là có thể quan sát được dưới dạng gốc của bạn. Bạn có thể mở rộng các quan sát bằng cách sử dụng extenders hoặc bằng cách thêm vào đối tượng được chia sẻ fn như được mô tả here. Tôi thích cái sau.

Vì vậy, bạn có thể thêm hàm vào các quan sát được gọi là withCurrencyFormat. Nó có thể trông giống như:

ko.observable.fn.withCurrencyFormat = function(precision) { 
    var observable = this; 
    observable.formatted = ko.computed({ 
     read: function (key) { 
      return '$' + (+observable()).toFixed(precision); 
     }, 
     write: function (value) { 
      value = parseFloat(value.replace(/[^\.\d]/g, "")); 
      observable(isNaN(value) ? null : value); // Write to underlying storage 
     }   
    }); 

    return observable; 
}; 

Bây giờ, bạn có thể nói:

self.week1Amount = ko.observable(w1).withCurrencyFormat(2); 
self.week2Amount = ko.observable(w2).withCurrencyFormat(2); 
self.week3Amount = ko.observable(w3).withCurrencyFormat(2); 

và ràng buộc chống lại nó trong giao diện người dùng như:

<td><input data-bind="value: week1Amount.formatted" /></td> 
    <td><input data-bind="value: week2Amount.formatted" /></td> 
    <td><input data-bind="value: week3Amount.formatted" /></td> 

mẫu ở đây: http://jsfiddle.net/rniemeyer/xskJN/

Một lựa chọn là di chuyển điều này vào một ràng buộc, vì vậy bạn có thể để mô hình khung nhìn của mình một mình. Điều này sẽ sử dụng mã tương tự, nhưng trong một handler tùy chỉnh ràng buộc mà có thể trông giống như:

ko.bindingHandlers.valueAsCurrency = { 
    init: function(element, valueAccessor) { 
     var observable = valueAccessor(), 
      formatted = ko.computed({ 
       read: function (key) { 
        return '$' + (+observable()).toFixed(2); 
       }, 
       write: function (value) { 
        value = parseFloat(value.replace(/[^\.\d]/g, "")); 
        observable(isNaN(value) ? null : value); // Write to underlying storage 
       }, 
       disposeWhenNodeIsRemoved: element     
      }); 

     //apply the actual value binding with our new computed 
     ko.applyBindingsToNode(element, { value: formatted }); 
    }   
}; 

Vì vậy, trong xử lý ràng buộc chúng tôi là tạo ra tính và sau đó sử dụng value ràng buộc chống lại nó của chúng tôi.

Bây giờ, mô hình điểm của bạn sẽ không cần thay đổi và bạn sẽ ràng buộc trong giao diện người dùng như:

<td><input data-bind="valueAsCurrency: week1Amount" /></td> 
    <td><input data-bind="valueAsCurrency: week2Amount" /></td> 
    <td><input data-bind="valueAsCurrency: week3Amount" /></td> 

mẫu ở đây: http://jsfiddle.net/rniemeyer/sD6y4/

+0

Cảm ơn, RP. Nó hoạt động hoàn hảo. –

+0

Tôi có một câu hỏi khác, cách áp dụng điều này cho trường tổng, là trường chỉ đọc. Một lần nữa, mã không hoạt động của tôi là http://jsfiddle.net/sD6y4/4/. Vì tôi có sum1, sum2, ..., các trường. Có thể thực hiện chức năng có thể tái sử dụng trong trường hợp này không? Cảm ơn trước! –

+0

Bạn có thể thêm một ràng buộc 'textAsCurrency' mà chỉ thực hiện phần' read' và áp dụng ràng buộc 'text'. Có thể trông giống như: http://jsfiddle.net/rniemeyer/3nrKD/ –