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

53,453

Solution 1

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

Solution 2

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.

Solution 3

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

Solution 4

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

Share:
53,453
Julien
Author by

Julien

Updated on July 27, 2020

Comments

  • Julien
    Julien almost 4 years

    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 other tools) without actually tracking each blur events on the inputs and updating the model manually? This seems like a lot of glue code.

    Thanks,
    Julien

  • Julien
    Julien over 13 years
    I ended up doing exactly that. I works great so far. As you said it saves on every change on the input. The errors are then displayed immediatly, which is good and bad (unmodified fields would display errors like can't be blank when creating a record).
  • clyfe
    clyfe over 13 years
    1. one can also try the blur event. 2. I've been pondering on this issue, it would be useful to have a "bindings" array has similar to the "events" hash that specify updates between view parts and model attributes with sync-type parameters (at_change, at_blur etc). say similar to bindings: [["div#title", "model.title", "change", "<-"], ["input#description", "model.description", "change", "<->"]] or something like that, it should be pretty easy to implement.
  • Julien
    Julien over 13 years
    I think you can use Handlebar.js as a templating engine. It has this kind of bindings.
  • bradgonesurfing
    bradgonesurfing almost 13 years
    I'd like to see this library! Is it available yet?
  • serverpunk
    serverpunk almost 13 years
    Posting generated output isn't particularly helpful for CoffeeScript examples of any size - it's ugly and hard to read because the output is intended for an interpreter, not for reading. You'd never write JavaScript that way by hand. For that reason, it baffles me that so many Coffeescript examples do this at the end with the customary "JavaScript - eww!"
  • bradgonesurfing
    bradgonesurfing almost 13 years
    You can't make anyone happy these days. Just post coffeescript raymond complains. Make an edit and include the translation and insin complains. Given that the question was about form binding in backbone my answer was on topic and probably the most idiomatic backbone solution. The question was about jquery and backbone not javascript specifically.
  • Jens Alm
    Jens Alm almost 13 years
    Unfortunately it isn't ready for general consumption yet, but we hope to have it up by august (gotta ship the product first before I can take the time to clean it up and generalize it properly)
  • UpTheCreek
    UpTheCreek over 12 years
    @clyfe - hi, shouldn't the events read "change input.content": "contentChanged"? Unless I'm missing something.
  • btiernay
    btiernay almost 12 years
    Would var obj = {}[changed.id] = value; work better than: var obj = "{\""+changed.id +"\":\""+value+"\"}"; var objInst = JSON.parse(obj);
  • LoG
    LoG almost 12 years
    You should never rely on something like: "{\""+changed.id +"\":\""+value+"\"}" at least serialize/escape the value string if you must.
  • Bill Ortell
    Bill Ortell over 11 years
    On changed will accommodate more 'html form elements' altogether - moreover 'blur', 'focus', 'onkeyup' - but, if you continue down this path, it's possible for you to just to implement the age-old 'setTimeout' and 'clearTimeout' solution with a delay on whether to trigger the event or not - ESPECIALLY if you have potentially more than one person 'saving' / 'updating' the model at a time... to constantly save on 'onChange' is really a burden on ur server/site. (just sayin')
  • Joe Johnson
    Joe Johnson over 11 years
    You don't need to pass an object to model.set(). In other words, you could use the following: this.model.set(target.name,target.value);
  • bradgonesurfing
    bradgonesurfing about 11 years
    Backbone is old hat these days. You should be using angularjs if you want super powered bindings.
  • chug2k
    chug2k over 10 years
    Kind of random question, but does one really need the _bindAll? Maybe it's something that's changed since this was written, but I think delegateEvents takes care of binding this for you.
  • JamieJag
    JamieJag about 10 years
    This same idea has been augmented and implemented as a plug-in: lostechies.com/derickbailey/2011/07/24/…
  • John Cromartie
    John Cromartie about 10 years
    @porcoesphino excuse me? I don't think I participated on this post.
  • Bodey Baker
    Bodey Baker about 10 years
    @JohnCromartie, yeah the post isn't there anymore. It was something like "this is an awful way to implement it" without any explanation why. I'll delete my comment but first: Do you still think it's awful? If so, why?