2012-05-19 15 views
8

Necesito validar un campo de texto de formulario que está vinculado a una propiedad de un modelo que usa EmberJS. Quiero que el usuario solo pueda escribir números válidos y válidos.¿Validar EmberJS TextField sobre la marcha?

Sé de jQuery.isNumber(), pero no sé cómo conectarlo al campo. Intenté escribir funciones getter/setter explícitas en la propiedad del modelo usando Ember.computed (...), pero no funcionó.

¿Hay algo similar al evento WinForms onChanging() que puedo conectar?

+0

Si no te importan los navegadores antiguos, puedes aprovechar el tipo de entrada html5 "number" también, como: {{view Ember.TextField type = "number" valueBinding = "someBinding"}} – Rajat

+0

@Rajat Entonces, ¿qué pasaría con los navegadores antiguos? ¿Funcionalidad rota o simplemente sin validación? ¿Y qué se considera "viejo"? (Lo siento, soy un novato en esta área) –

+0

Simplemente recurrirán a un campo de texto normal. En el soporte del navegador, compruebe el modo peculiar: http://www.quirksmode.org/html5/inputs.html – Rajat

Respuesta

14

Hay un número de maneras de hacer este tipo de cosas. Aquí podemos lograr esto usando enlaces y observadores.

Primero permitamos crear una función que siempre devolverá un número.

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

usando lo que podemos hacer la siguiente

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) Estamos creando una unión a la edad de la persona, pero cualquier cosa que pasa a través de esta unión sólo puede ser un número. Ver Ember.Binding para/desde transformaciones para más detalles.

2) Estamos observando el valor del campo de texto y configurándolo como un número cuando cambia. Si el usuario ingresa '42a', lo restableceremos inmediatamente a '42'. Tenga en cuenta que, aunque '42a' estuvo en la entrada de texto por un breve segundo, no habría podido pasar a través del enlace debido a nuestra transformación.

Aquí es un violín que muestra este ejemplo: http://jsfiddle.net/nDBgC/

+0

¡Impresionante! Gracias por la explicación detallada. –

+0

Miré transformaciones y aparentemente hay una forma abreviada de que ambas direcciones de la transformación funcionen igual. He modificado la respuesta para reflejarlo. –

+3

Creo que el código de validación tiene más sentido en el modelo que en la vista. Su idea de "observador" se ajusta perfectamente a la factura y no se necesitan enlaces personalizados (o vistas personalizadas). He bifurcado un violín (por cierto, esto suena sucio) en tu ejemplo: http://jsfiddle.net/L6vmc/4/ –

3

Se podría añadir un controlador de keyDown evento en su campo de texto, ver 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

Hombre, esto me parece ASM. Es tipo de navegador ASM. –

+0

Usted indicó "Quiero que el usuario solo pueda escribir números válidos y válidos". Eso es lo que hace este fragmento ... – pangratz

+0

"Eso es lo que hace este fragmento" -> He visto toneladas de código que hacen lo que deberían ... Pero todavía pueden ser un horror. – yagooar

1

Código (maneja la entrada única numérico y permite la unión de número en lugar de la secuencia, si se desea):

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

Plantilla:

{{number-field numericValue=someNumericProperty}} 
0

Esta es una respuesta actualizada (de @neverfox) para la última versión de Ember (Ember-cli 2.0). Está escrito en CoffeeScript, y un poco alterado para que coincida con el ejemplo becomeFocus (http://guides.emberjs.com/v1.10.0/cookbook/user_interface_and_interaction/focusing_a_textfield_after_its_been_inserted/)

  1. Generar el componente:

    brasa g componente número de campo

  2. Cambiar el código de modelo (app /components/number-field.coffee) a

`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`

Cuestiones relacionadas