2012-05-19 29 views
8

Tôi cần phải xác thực một trường văn bản biểu mẫu được ràng buộc với thuộc tính của một mô hình sử dụng EmberJS. Tôi muốn người dùng chỉ có thể nhập số hợp lệ, số dương.Xác thực TextField của EmberJS khi đang di chuyển?

Tôi biết về jQuery.isNumber(), nhưng tôi không biết cách kết nối nó với trường. Tôi đã thử viết các hàm getter/setter rõ ràng trên thuộc tính của mô hình bằng cách sử dụng Ember.computed (...), nhưng nó không hoạt động.

Có điều gì tương tự với sự kiện WinForms onChanging() mà tôi có thể kết nối không?

+0

Nếu bạn không quan tâm đến các trình duyệt cũ, bạn cũng có thể tận dụng loại đầu vào html5 "số", như: {{view Ember.TextField type = "number" valueBinding = "someBinding"}} – Rajat

+0

@Rajat Vậy điều gì sẽ xảy ra với các trình duyệt cũ? Chức năng bị hỏng hoặc đơn giản là không xác nhận? Và những gì được coi là 'cũ'? (Xin lỗi, tôi là một noob trong lĩnh vực này) –

+0

Họ sẽ chỉ đơn giản là dự phòng cho một trường văn bản thông thường. Trên trình duyệt hỗ trợ kiểm tra quirksmode: http://www.quirksmode.org/html5/inputs.html – Rajat

Trả lời

14

Có một số cách để làm việc này. Ở đây chúng ta có thể thực hiện điều này bằng cách sử dụng các ràng buộc và quan sát viên.

Đầu tiên cho phép tạo một hàm luôn trả về một số.

var onlyNumber = function(input) { 
    return input.toString().replace(/[^\d.]/g, ""); 
}; 

Sử dụng mà chúng ta có thể làm như sau

App = Ember.Application.create(); 

App.person = Ember.Object.create({ 
    age: 42 
}); 

App.NumberField = Ember.TextField.extend({ 
    valueBinding: Ember.Binding.from("App.person.age").transform(onlyNumber), 

    _cleanValue: function() { 
     this.set('value', onlyNumber(this.get('value'))); 
    }.observes('value') 
}); 

1) Chúng tôi đang tạo ra một Binding tuổi của Người, nhưng bất cứ điều gì mà đi qua ràng buộc này chỉ có thể là một số. Xem Ember.Binding đến/từ các phép biến đổi để biết thêm chi tiết.

2) Chúng tôi đang quan sát giá trị của trường văn bản và đặt giá trị đó thành một số khi nó thay đổi. Nếu người dùng nhập '42a', chúng tôi sẽ đặt ngay lập tức trở lại '42'. Lưu ý rằng mặc dù '42a' nằm trong đầu vào văn bản trong một giây ngắn ngủi nhưng nó sẽ không thể vượt qua ràng buộc do biến đổi của chúng ta.

Đây là một fiddle cho thấy ví dụ này: http://jsfiddle.net/nDBgC/

+0

Tuyệt vời! Cảm ơn vì lời giải thích chi tiết. –

+0

Tôi nhìn vào biến đổi và dường như có một cách viết tắt nếu cả hai hướng của biến đổi làm việc giống nhau. Tôi đã sửa đổi câu trả lời để phản ánh nó. –

+3

Tôi nghĩ mã xác nhận có ý nghĩa hơn trong mô hình so với trong chế độ xem, ý tưởng 'quan sát' của bạn phù hợp với hóa đơn một cách hoàn hảo và không cần có các ràng buộc tùy chỉnh (hoặc chế độ xem tùy chỉnh). Tôi đã chia rẽ một fiddle (btw này âm thanh bẩn) từ ví dụ của bạn: http://jsfiddle.net/L6vmc/4/ –

3

Bạn có thể thêm một handler keyDown sự kiện trên TextField bạn, hãy xem http://jsfiddle.net/pangratz666/SKJfF/:

App.NumberTextField = Ember.TextField.extend({ 
    // implementation of this function, see http://stackoverflow.com/a/995193/65542 
    keyDown: function(event) { 
     // Allow: backspace, delete, tab, escape, and enter 
     if (event.keyCode == 46 || event.keyCode == 8 || event.keyCode == 9 || event.keyCode == 27 || event.keyCode == 13 || 
     // Allow: Ctrl+A 
     (event.keyCode == 65 && event.ctrlKey === true) || 
     // Allow: home, end, left, right 
     (event.keyCode >= 35 && event.keyCode <= 39)) { 
      // let it happen, don't do anything 
      return; 
     } 
     else { 
      // Ensure that it is a number and stop the keypress 
      if (event.shiftKey || (event.keyCode < 48 || event.keyCode > 57) && (event.keyCode < 96 || event.keyCode > 105)) { 
       event.preventDefault(); 
      } 
     } 
    } 
});​ 
+4

Con người, điều này trông giống như ASM với tôi. Đó là loại trình duyệt-ASM. –

+0

Bạn đã nói "Tôi muốn người dùng chỉ có thể nhập số hợp lệ, số dương". Đó là những gì đoạn mã này làm ... – pangratz

+0

"Đó là những gì đoạn này hiện" -> Tôi đã thấy tấn mã mà làm những gì họ nên ... Nhưng họ vẫn có thể là một kinh dị. – yagooar

1

Mã (xử lý đầu vào chỉ số và cho phép ràng buộc của số chứ không phải là chuỗi, nếu muốn):

App.NumberFieldComponent = Ember.TextField.extend({ 
    tagName: "input", 
    type: "number", 

    numericValue: function(key, value) { 
    if (arguments.length === 1) { 
     return parseFloat(this.get("value")); 
    } else { 
     return this.set("value", (value !== void 0 ? "" + value : "")); 
    } 
    }.property("value"), 

    didInsertElement: function() { 
    return this.$().keypress(function(key) { 
     if ((key.charCode !== 46) && (key.charCode !== 45) && (key.charCode < 48 || key.charCode > 57)) { 
     return false; 
     } 
    }); 
    } 
}); 

mẫu:

{{number-field numericValue=someNumericProperty}} 
0

Đây là câu trả lời được cập nhật (từ @neverfox) cho phiên bản Ember mới nhất (Ember-cli 2.0). Nó được viết bằng coffeescript, và một chút thay đổi để phù hợp với ví dụ becomeFocus (http://guides.emberjs.com/v1.10.0/cookbook/user_interface_and_interaction/focusing_a_textfield_after_its_been_inserted/)

  1. Tạo các thành phần:

    ember g thành phần số trường

  2. Thay đổi mã kế hoạch chi tiết (ứng dụng /components/number-field.coffee) để

`import Ember from 'ember'` 
 
    
 
    NumberFieldComponent = Ember.Component.extend 
 
     tagName: "input" 
 
     type: "number" 
 
    
 
    \t numericValue: ((key, value) -> 
 
    \t \t if arguments.length == 1 
 
    \t \t \t parseFloat(this.get('value')) 
 
    \t \t else 
 
    \t \t \t return this.set("value", (value? ? "" + value : "")) 
 
    \t).property('value') 
 
    
 
    \t assignFilter: (-> 
 
    \t \t this.$().keypress (key) -> 
 
    \t \t \t if ((key.charCode != 46) && (key.charCode != 45) && (key.charCode < 48 || key.charCode > 57)) 
 
    \t \t \t \t false 
 
    \t).on('didInsertElement') 
 
      \t \t 
 
    
 
    `export default NumberFieldComponent`

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