Can I bind form inputs to models in Backbone.js without manually tracking blur events?

后端 未结 6 1483
抹茶落季
抹茶落季 2021-01-29 18:32

I have a backbone.js app (www.github.com/juggy/job-board) where I want to bind my form inputs directly to my model (a la Sproutcore).

Is it possible with Backbone.js (or

相关标签:
6条回答
  • 2021-01-29 18:40

    Have you tried Backbone.ModelBinder? It´s a nice tool to do what you need: https://github.com/theironcook/Backbone.ModelBinder

    0 讨论(0)
  • 2021-01-29 18:40

    I'm working on corset, a form library for backbone.js inspired by the django forms module, but a little less ambitious in scope. Still working out the kinks, but it'll end up on github when at least semi-stable and functional.

    The aim of corset is to have easily subclassed field classes so that you can build complex inputs for more complex use cases (cascading selects, etc). This approach renders each field as a separate view, and the form view is bound to a model and uses change events, blur events or submit events to update the model (configurable, blur is default). Each view has an overrideable getData function that per default maps to the jquery .val() function.

    Using sensible defaults and a modelFormFactory function, we use corset (or the subset of it that is actually done yet) for rapid development, define a model using sensible attribute names, use modelFormFactory and you have instant edit UI.

    0 讨论(0)
  • 2021-01-29 18:45

    I think this is a cleaner (and maybe faster) way to create an object from an input element

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

    without jquery:

    changed: function(evt) {
      var target = evt.currentTarget,
          data = {};
      data[target.name] = target.value;
      this.model.set(data);
    },
    
    0 讨论(0)
  • 2021-01-29 18:48

    I'm not sure how SC does it but probably they listen for events too.

    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 讨论(0)
  • 2021-01-29 18:56

    There is an even nicer way to handle this if your model includes lots of properties in it.

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

    There is a reliance on your input elements having an id the same as the what the name of the property in your model is.

    0 讨论(0)
  • 2021-01-29 19:03

    I created the following technique on my site

    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) 
    

    I've detailed the extensions to backbone you need to make on my blog

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

    it uses the same declarative style as the events property for binding form elements to model attributes

    and here is the actual code implementing the class for you 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
    
        @
    

    Appologies if you don't like coffeescript. I do. Everybody is different :)

    0 讨论(0)
提交回复
热议问题