2012-05-19 18 views
8

Devo convalidare un campo di testo del modulo associato a una proprietà di un modello utilizzando EmberJS. Voglio che l'utente sia in grado di digitare solo numeri positivi validi.Convalidare EmberJS TextField al volo?

Conosco jQuery.isNumber(), ma non so come collegarlo al campo. Ho provato a scrivere esplicite funzioni getter/setter sulla proprietà del modello usando Ember.computed (...), ma non ha funzionato.

C'è qualcosa di simile all'evento di WinForms onChanging() a cui posso collegarmi?

+0

Se non ti piacciono i vecchi browser, puoi sfruttare anche il tipo di numero di input html5, come: {{visualizza Ember.TextField type = "number" valueBinding = "someBinding"}} – Rajat

+0

@Rajat Cosa succederebbe con i vecchi browser? Funzionalità interrotta o semplicemente nessuna convalida? E cosa si considera "vecchio"? (Scusate, sono un noob in quest'area) –

+0

Riporteranno semplicemente in un normale campo di testo. Sul supporto del browser, controlla quirksmode: http://www.quirksmode.org/html5/inputs.html – Rajat

risposta

14

Ci sono un certo numero di modi per fare questo genere di cose. Qui possiamo realizzare questo usando associazioni e osservatori.

Prima consente di creare una funzione che restituirà sempre un numero.

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

usando che possiamo fare le seguenti

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) Stiamo creando un legame alle età della persona, ma tutto ciò che passa attraverso questo legame può essere solo un numero. Vedi Ember.Binding da/per le trasformazioni per maggiori dettagli.

2) Stiamo osservando il valore del campo di testo e impostandolo come un numero solo quando cambia. Se l'utente immette "42a", verrà immediatamente impostato su "42". Si noti che anche se "42a" era inserito nel testo per un breve secondo, non sarebbe stato in grado di passare attraverso l'associazione a causa della nostra trasformazione.

Ecco un violino che mostra questo esempio: http://jsfiddle.net/nDBgC/

+0

Fantastico! Grazie per la spiegazione dettagliata. –

+0

Ho guardato le trasformazioni e apparentemente c'è una scorciatoia se entrambe le direzioni della trasformazione funzionano allo stesso modo. Ho modificato la risposta per rifletterlo. –

+3

Penso che il codice di validazione abbia più senso nel modello che nella vista. La tua idea di "osservatore" si adatta perfettamente alla fattura e non sono necessari collegamenti personalizzati (o viste personalizzate). Ho biforcato un violino (che sembra sporco) dal tuo esempio: http://jsfiddle.net/L6vmc/4/ –

3

Si potrebbe aggiungere un gestore di eventi keyDown sul TextField, vedere 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

Man, mi sembra ASM. È tipo browser ASM. –

+0

Hai dichiarato "Voglio che l'utente sia in grado di digitare solo numeri positivi validi". Questo è ciò che questo frammento fa ... – pangratz

+0

"Questo è ciò che fa questo frammento" -> Ho visto tonnellate di codice che fanno quello che dovrebbero ... Ma possono ancora essere un orrore. – yagooar

1

Codice (gestisce l'input solo numerica e permette legame di numero, piuttosto che di stringa, se lo si desidera):

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}} 
0

Questa è una risposta aggiornata (da @neverfox) per l'ultima versione di Ember (Ember-cli 2.0). E 'scritto in CoffeeScript, e un po' alterata per abbinare l'esempio becomeFocus (http://guides.emberjs.com/v1.10.0/cookbook/user_interface_and_interaction/focusing_a_textfield_after_its_been_inserted/)

  1. Generare il componente:

    brace g componente numero campo

  2. Modificare il codice progetto (app /components/number-field.coffee) per

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