2011-10-20 2 views
14

Immaginate un semplice modello di spina dorsale comeBackbone.js - setter personalizzati

window.model= Backbone.Model.extend({ 
    defaults:{ 
     name: "", 
     date: new Date().valueOf() 
    } 
}) 

Sto cercando di trovare un modo per rendere sempre il negozio modello il nome in lettere minuscole, indipendentemente dell'input fornito. Ad esempio,

model.set({name: "AbCd"}) 
model.get("name") // prints "AbCd" = current behavior 
model.get("name") // print "abcd" = required behavior 

Qual è il modo migliore per farlo? Ecco tutto quello che riuscivo a pensare:

  1. l'override del metodo "set"
  2. Utilizzare un "SantizedModel" che attenda le modifiche su questo modello di base e memorizza gli ingressi igienizzati. Il codice di visualizzazione di tutti verrà quindi passato a questo modello igienizzato.

La specifica "in minuscolo" esempio ho citato può tecnicamente essere più efficacemente dalla vista durante il recupero, ma immaginare un diverso caso in cui, ad esempio, l'utente inserisce valori in sterline e voglio solo memorizzare valori in $ s nel mio database. Potrebbero esserci anche viste diverse per lo stesso modello e non voglio dover fare un "toLowerCase" ovunque sia usato.

Pensieri?

risposta

5

Sarebbe un hack, perché questo non è ciò che è stato fatto per, ma si può sempre usare un validatore per questo:

window.model= Backbone.Model.extend({ 
    validate: function(attrs) { 
     if(attrs.name) { 
     attrs.name = attrs.name.toLowerCase() 
     } 

     return true; 
    } 
}) 

La funzione di convalida verrà chiamato (a condizione che il silent l'opzione non è impostata) prima che il valore sia impostato nel modello, quindi ti dà la possibilità di mutare i dati prima che siano realmente impostati.

+0

Grazie. Ho preso in considerazione anche questo, ma questo sembrava essere un passo indietro in termini di renderlo leggibile: ignorare la funzione set o aggiungere una nuova funzione "setProperty" che lo imposta in minuscolo e quindi lo passa nel set backbone potrebbe essere migliore. A meno che mi manchi qualcosa? – Naren

+0

Non c'è sicuramente niente di sbagliato nell'override del metodo 'set' per fare ciò che è necessario per fare ... qualche pre-elaborazione prima del set? Potresti anche considerare di estendere 'Backbone.Model.prototype.set' per chiamare alcuni pre-processori se corrispondono ... qualcosa del genere: https://gist.github.com/1310972 –

+0

convalida viene chiamato solo per il metodo di salvataggio o se options.validate = true è impostato. (silenzioso non è usato qui, ma la risposta è piuttosto vecchia) – webstrap

10

UPDATE: è possibile utilizzare il plug-in: https://github.com/berzniz/backbone.getters.setters


È possibile eseguire l'override del metodo set come questo (aggiungerlo ai tuoi modelli):

set: function(key, value, options) { 
    // Normalize the key-value into an object 
    if (_.isObject(key) || key == null) { 
     attrs = key; 
     options = value; 
    } else { 
     attrs = {}; 
     attrs[key] = value; 
    } 

    // Go over all the set attributes and make your changes 
    for (attr in attrs) { 
     if (attr == 'name') { 
      attrs['name'] = attrs['name'].toLowerCase(); 
     } 
    } 

    return Backbone.Model.prototype.set.call(this, attrs, options); 
} 
+3

invece di un ciclo, consiglierei se (attrs.name) attrs.name = attrs.name.toLowerCase(); – webstrap

+0

noti che se il primo paramter è un oggetto, l'impostazione degli attributi è delegato 'set' con una stringa come primo parametro. Quindi la normalizzazione è necessaria solo se il primo parametro è una stringa. – Webthusiast

3

Non a toot il mio corno, ma I created a Backbone model con proprietà "Computed" per aggirare questo. In altre parole

var bm = Backbone.Model.extend({ 
    defaults: { 
    fullName: function(){return this.firstName + " " + this.lastName}, 
    lowerCaseName: function(){ 
     //Should probably belong in the view 
     return this.firstName.toLowerCase(); 

    } 
    } 
}) 

È anche ascoltare per le modifiche sulle proprietà calcolate e praticamente solo considerare questo come uno normale.

The plugin Bereznitskey mentioned è anche un approccio valido.

+0

Sto provando questo ora e sta riecheggiando la mia funzione effettiva piuttosto che il valore di ritorno. 'default: {distance: function() {return 10; }} , '' quindi console.log (this.model.get ('distanza')); '?? – trapper

+0

@trapper - stai estendendo dal "BasecomputedModel" dal github collegato? – Naren