2010-11-02 7 views
62

Tengo una aplicación backbone.js (www.github.com/juggy/job-board) donde quiero vincular las entradas de mi formulario directamente a mi modelo (a la Sproutcore).¿Puedo vincular entradas de formulario a modelos en Backbone.js sin seguir manualmente los eventos de desenfoque?

¿Es posible con Backbone.js (u otras herramientas) sin rastrear realmente cada evento de desenfoque en las entradas y actualizar el modelo manualmente? Esto parece mucho código de pegamento.

Gracias,
Julien

Respuesta

34

No estoy seguro de cómo lo hace SC pero es probable que escuchar los sucesos también.

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

Terminé haciendo exactamente eso. Yo trabajo muy bien hasta ahora. Como dijiste ahorra en cada cambio en la entrada. Los errores se muestran inmediatamente, lo que es bueno y malo (los campos no modificados mostrarán errores como no pueden estar en blanco al crear un registro). – Julien

+2

1. también se puede probar el evento blur. 2. He estado reflexionando sobre este tema, sería útil tener una matriz de "enlaces" similar al hash "de eventos" que especifique las actualizaciones entre las partes de la vista y los atributos del modelo con parámetros de tipo de sincronización (at_change, at_blur, etc.) . say similar a 'bindings: [[" div # title "," model.title "," change "," <- "], [" input # description "," model.description "," change "," <-> " ]] 'o algo así, debería ser bastante fácil de implementar. – clyfe

+0

Creo que puedes usar Handlebar.js como un motor de plantillas. Tiene este tipo de enlaces. – Julien

52

Hay una manera aún más agradable de manejar esto si su modelo incluye muchas propiedades en él.

SampleView = Backbone.View.extend({ 
    el: "#formEl", 

    events: { 
     "change input": "changed", 
     "change select": "changed" 
    }, 

    initialize: function() { 
     _.bindAll(this, "changed"); 
    }, 

    changed:function (evt) { 
     var changed = evt.currentTarget; 
     var value = $(evt.currentTarget).val(); 
     var obj = {}; 
     obj[changed.id] = value; 
     this.model.set(obj); 
    } 
}); 

Depende de sus elementos de entrada que tienen una identificación igual a la que es el nombre de la propiedad en su modelo.

+1

Var varj = {} [changed.id] = value; funcionan mejor que: var obj = "{\" "+ changed.id +" \ ": \" "+ value +" \ "}"; var objInst = JSON.parse (obj); – btiernay

+0

Nunca debe confiar en algo como: '" {\ "" + changed.id + "\": \ "" + value + "\"} "' al menos serialize/escape la cadena de valor si es necesario. – LoG

+0

Esta misma idea se ha aumentado e implementado como un complemento: http://lostechies.com/derickbailey/2011/07/24/awesome-model-binding-for-backbone-js/ – JamieJag

18

Creo que este es un producto de limpieza (y tal vez más rápido) manera de crear un objeto a partir de un elemento de entrada

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

sin jQuery:

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

No necesita pasar un objeto a model.set(). En otras palabras, podría usar lo siguiente: this.model.set (target.name, target.value); –

1

estoy trabajando en el corsé, una forma biblioteca para backbone.js inspirada en el módulo de formularios django, pero con un alcance un poco menos ambicioso. Aún estoy resolviendo los problemas, pero terminará en github cuando sea al menos semi-estable y funcional.

El objetivo del corsé es tener clases de campo fácilmente subclasificadas para que pueda crear entradas complejas para casos de uso más complejos (selecciones en cascada, etc.). Este enfoque representa cada campo como una vista separada, y la vista de formulario está vinculada a un modelo y utiliza eventos de cambio, desenfoque de eventos o envía eventos para actualizar el modelo (configurable, el desenfoque es el predeterminado). Cada vista tiene una función getData anulable que se asigna por defecto a la función jquery .val().

Usando valores predeterminados razonables y una función modelFormFactory, usamos el corsé (o el subconjunto que ya está hecho) para un desarrollo rápido, definimos un modelo usando nombres de atributos sensibles, usamos modelFormFactory y tenemos UI de edición instantánea.

+0

¡Me gustaría ver esta biblioteca! Está disponible? – bradgonesurfing

+0

Lamentablemente todavía no está listo para el consumo general, pero esperamos tenerlo en agosto (tengo que enviar el producto antes de poder tomarme el tiempo para limpiarlo y generalizarlo correctamente) –

0

creé la siguiente técnica en mi sitio

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) 

he detallado las ampliaciones de la columna vertebral que necesita para hacer en mi blog

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

que utiliza el mismo estilo declarativo la propiedad de eventos para vincular los elementos de formulario con los atributos del modelo

y aquí está el código real implementación de la clase para ti en 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 

    @ 

appologies si no te gusta CoffeeScript. Hago. Todos son diferentes :)

+8

Publicación de la salida generada no es particularmente útil para los ejemplos de CoffeeScript de cualquier tamaño: es feo y difícil de leer porque el resultado está destinado a un intérprete, no a la lectura. Nunca escribirías JavaScript de esa manera a mano. Por esa razón, me desconcierta que tantos ejemplos de Coffeescript lo hagan al final con el "JavaScript - ¡eww!" Habitual. –

+7

No puede hacer feliz a nadie en estos días. Solo publique coffeescript Raymond se queja. Realice una edición e incluya las quejas de traducción e insinuación. Dado que la pregunta era sobre el enlace de formularios en la red troncal, mi respuesta fue sobre el tema y probablemente la solución de columna vertebral más idiomática. La pregunta era sobre jquery y backbone no javascript específicamente. – bradgonesurfing

+0

Backbone es viejo sombrero en estos días. Deberías usar angularjs si quieres enlaces súper potenciados. – bradgonesurfing

Cuestiones relacionadas