2010-11-02 4 views
62

Ho un'app backbone.js (www.github.com/juggy/job-board) dove voglio associare gli input del mio modulo direttamente al mio modello (a la Sproutcore).È possibile associare gli input dei moduli ai modelli in Backbone.js senza tenere traccia manualmente degli eventi di sfocatura?

E 'possibile con Backbone.js (o altri strumenti) senza effettivamente tenere traccia di ogni evento sfocato sugli ingressi e aggiornare manualmente il modello? Questo sembra un sacco di codice della colla.

Grazie,
Julien

risposta

34

io non sono sicuro di come SC fa ma probabilmente ascoltano per gli eventi troppo.

window.SomeView = Backbone.View.extend({ 
    events: { 
    "change input.content": "contentChanged" 
    }, 
    initialize: function() { 
    _.bindAll(this, 'contentChanged'); 
    this.inputContent = this.$('input.content'); 
    }, 
    contentChanged: function(e) { 
    var input = this.inputContent; 

    // if you use local storage save 
    this.model.save({content: input.val()}); 

    // if you send request to server is prob. good idea to set the var and save at the end, in a blur event or in some sync. maintenance timer. 
    // this.model.set({content: input.val()}); 
    } 
}); 
+0

Ho finito per fare esattamente questo. Io lavoro molto bene finora. Come hai detto, salva ogni modifica sull'input. Gli errori vengono visualizzati immediatamente, il che è positivo e negativo (i campi non modificati visualizzano errori come non possono essere vuoti durante la creazione di un record). – Julien

+2

1. si può anche provare l'evento sfocatura. 2. Ho riflettuto su questo problema, sarebbe utile avere un array "binding" simile all'hash "events" che specifica gli aggiornamenti tra le parti view e gli attributi del modello con parametri di tipo sync (at_change, at_blur etc) . diciamo simile a 'binding: [[" div # title "," model.title "," change "," <- "], [" input # description "," model.description "," change "," <-> " ]] 'o qualcosa del genere, dovrebbe essere abbastanza facile da implementare. – clyfe

+0

Penso che tu possa usare Handlebar.js come motore di template. Ha questo tipo di legami. – Julien

52

Esiste un modo ancora migliore per gestirlo se il modello include molte proprietà al suo interno.

C'è un affidamento sugli elementi di input con un ID uguale a quello che è il nome della proprietà nel modello.

+1

Would var obj = {} [changed.id] = valore; funziona meglio di: var obj = "{\" "+ changed.id +" \ ": \" "+ value +" \ "}"; var objInst = JSON.parse (obj); – btiernay

+0

Non dovresti mai fare affidamento su qualcosa del tipo: '" {\ "" + changed.id + "\": \ "" + value + "\"} "' Almeno serializza/esci dalla stringa del valore se necessario. – LoG

+0

Questa stessa idea è stata aumentata e implementata come plug-in: http://lostechies.com/derickbailey/2011/07/24/awesome-model-binding-for-backbone-js/ – JamieJag

18

Credo che questo sia un detergente (e forse più veloce) modo per creare un oggetto da un elemento input

changed: function(evt) { 
    var target = $(evt.currentTarget), 
     data = {}; 
    data[target.attr('name')] = target.val(); 
    this.model.set(data); 
}, 

senza jquery:

changed: function(evt) { 
    var target = evt.currentTarget, 
     data = {}; 
    data[target.name] = target.value; 
    this.model.set(data); 
}, 
+2

Non è necessario passare un oggetto a model.set(). In altre parole, è possibile utilizzare quanto segue: this.model.set (target.name, target.value); –

1

sto lavorando su corsetto, una forma libreria per backbone.js ispirata al modulo django forms, ma un po 'meno ambiziosa. Stiamo ancora lavorando sui nodi, ma finirà su Github quando almeno semi-stabile e funzionale.

L'obiettivo del corsetto è di avere classi di campo facilmente sottoclasse in modo da poter creare input complessi per casi d'uso più complessi (selezione a cascata, ecc.). Questo approccio rende ogni campo come una vista separata, e la vista modulo è associata a un modello e utilizza gli eventi di modifica, gli eventi di sfocatura o l'invio di eventi per aggiornare il modello (configurabile, la sfocatura è predefinita). Ogni vista ha una funzione getData sovrascrivibile che, per impostazione predefinita, esegue il mapping alla funzione jquery .val().

Utilizzando le impostazioni predefinite sensibili e una funzione modelFormFactory, utilizziamo il corsetto (o il sottoinsieme di esso effettivamente eseguito) per lo sviluppo rapido, definiamo un modello utilizzando nomi di attributi sensibili, use modelFormFactory e l'interfaccia utente di modifica immediata.

+0

Mi piacerebbe vedere questa libreria! È ancora disponibile? – bradgonesurfing

+0

Purtroppo non è ancora pronto per il consumo generale, ma speriamo di averlo fino ad agosto (devo spedire il prodotto prima che possa prendermi il tempo per pulirlo e generalizzarlo in modo corretto) –

0

ho creato la seguente tecnica sul mio sito

class FooView extends MyView 

    tag: "div" 

    modelBindings: 

    "change form input.address" : "address" 
    "change form input.name" : "name" 
    "change form input.email" : "email" 

    render: -> 

    $(@el).html """ 
     <form> 
     <input class="address"/> 
     <input class="name"/> 
     <input class="email"/> 
     </form> 
    """ 

    super 

    @ 


# Instantiate the view 
view = new FooView 
    model: new Backbone.Model 

$("body").html(view.el) 

ho dettagliata L'estensioni al backbone è necessario fare sul mio blog

http://xtargets.com/2011/06/11/binding-model-attributes-to-form-elements-with-backbone-js/

utilizza lo stesso stile dichiarativo come la proprietà eventi per gli elementi del modulo vincolante per il modello attributi

e qui è il codice vero e implementando la classe per voi in CoffeeScript

class MyView extends Backbone.View 

    render: -> 

    if @model != null 
     # Iterate through all bindings 
     for selector, field of @modelBindings 
     do (selector, field) => 
      console.log "binding #{selector} to #{field}" 
      # When the model changes update the form 
      # elements 
      @model.bind "change:#{field}", (model, val)=> 
      console.log "model[#{field}] => #{selector}" 
      @$(selector).val(val) 

      # When the form changes update the model 
      [event, selector...] = selector.split(" ") 
      selector = selector.join(" ") 
      @$(selector).bind event, (ev)=> 
      console.log "form[#{selector}] => #{field}" 
      data = {} 
      data[field] = @$(ev.target).val() 
      @model.set data 

      # Set the initial value of the form 
      # elements 
      @$(selector).val(@model.get(field)) 

    super 

    @ 

scusato se non ti piace CoffeeScript. Lo voglio. Tutti sono diversi :)

+8

La pubblicazione di output generato non è particolarmente utile per gli esempi CoffeeScript di qualsiasi dimensione: è brutto e difficile da leggere perché l'output è destinato a un interprete, non alla lettura. Non scriverei mai JavaScript in quel modo a mano. Per questo motivo, mi sconcerta che tanti esempi di Coffeescript lo fanno alla fine con il solito "JavaScript - eww!" –

+7

Non puoi rendere felice nessuno in questi giorni. Basta postare il coffeescript per cui Raymond si lamenta. Fai una modifica e includi la traduzione e le lamentele di insin. Dato che la domanda riguardava la form binding in backbone, la mia risposta era sull'argomento e probabilmente la soluzione backbone più idiomatica. La domanda riguardava jQuery e backbone, non specificamente javascript. – bradgonesurfing

+0

Backbone è un vecchio cappello in questi giorni. Dovresti usare angularjs se vuoi i binding superpotenti. – bradgonesurfing