最新消息:雨落星辰是一个专注网站SEO优化、网站SEO诊断、搜索引擎研究、网络营销推广、网站策划运营及站长类的自媒体原创博客

javascript - Validate EmberJS TextField on the fly? - Stack Overflow

programmeradmin0浏览0评论

I need to validate a form textfield that's bound to a property of a model using EmberJS. I want the user to only be able to type valid, positive numbers.

I know of jQuery.isNumber(), but I don't know how to wire it to the field. I tried writing explicit getter/setter functions on the model's property using Emberputed(...), but it didn't work.

Is there something similar to WinForms onChanging() event that I can hook up to?

I need to validate a form textfield that's bound to a property of a model using EmberJS. I want the user to only be able to type valid, positive numbers.

I know of jQuery.isNumber(), but I don't know how to wire it to the field. I tried writing explicit getter/setter functions on the model's property using Ember.computed(...), but it didn't work.

Is there something similar to WinForms onChanging() event that I can hook up to?

Share Improve this question asked May 19, 2012 at 13:04 Cristian DiaconescuCristian Diaconescu 35.6k32 gold badges148 silver badges239 bronze badges 3
  • If you dont care for old browsers, you can take leverage of html5 input type "number" as well, like: {{view Ember.TextField type="number" valueBinding="someBinding"}} – Rajat Commented May 21, 2012 at 17:58
  • @Rajat So what would happen with old browsers? Broken functionality or simply no validation? And what is considered 'old' ? (Sorry, I'm a noob in this area) – Cristian Diaconescu Commented May 29, 2012 at 16:38
  • They will simply fallback to a regular textfield. On browser support check quirksmode: quirksmode.org/html5/inputs.html – Rajat Commented May 29, 2012 at 17:24
Add a comment  | 

4 Answers 4

Reset to default 14

There are a number of ways to do this sort of thing. Here we can accomplish this using bindings and observers.

First lets create a function that will always return a number.

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

Using that we can do the following

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) We are creating a Binding to the Person's age, but anything that passes through this binding can only be a number. See Ember.Binding to/from transforms for more details.

2) We are observing the text field's value and setting it to be only a number when it changes. If the user enters '42a' we will immediately set it back to '42'. Note that even though '42a' was in the text input for a brief second it would not have been able to pass through the binding because of our transform.

Here is a fiddle showing this example: http://jsfiddle.net/nDBgC/

You could add a keyDown event handler on your TextField, see 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();
            }
        }
    }
});​

Code (handles only numeric input and allows binding of number rather than string, if desired):

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;
      }
    });
  }
});

Template:

{{number-field numericValue=someNumericProperty}}

This is an updated answer (from @neverfox) for the latest Ember version (Ember-cli 2.0). It is written in coffeescript, and a bit altered to match the becomeFocus example (http://guides.emberjs.com/v1.10.0/cookbook/user_interface_and_interaction/focusing_a_textfield_after_its_been_inserted/)

  1. Generate the component:

    ember g component number-field

  2. Change the blueprint code (app/components/number-field.coffee) to

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

发布评论

评论列表(0)

  1. 暂无评论