Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Backbone.js model validation only on set->save (not on fetch)

Tags:

backbone.js

Caveat: I'm working with a backend that I don't have full control over, so I'm wrestling with a few considerations within Backbone that might be better addressed elsewhere...unfortunately, I have no choice but to handle them here!

So, my problem is that I'd really like to validate user input from a form (when I set values with it on Backbone models), but the models I receive from the API on newly created objects (via posts that ONLY accept a name, and ONLY return a name and object id) will fail my validation checks.

As example, when a new object is created in the database, two key fields are populated as empty strings (and so when Backbone hits the API and populates the models, it populates those keys with empty strings). When the user saves these objects back, post-edit, I'd like to force them to enter values for these two keys -- which is very easy, given Backbone's built in validation method.

The problem, of course, is that the validation is firing on both fetch->set (unwanted behavior) and set->save (desired behavior) -- and so newly created models won't load at all...Backbone collects them, validation fails, and errors fire.

So, my question is: is there a "Backbone-y" way to only validate the models on set->save, not on fetch->set? Could I use a specific trigger to work around this?

Any ideas would be greatly appreciated.

like image 786
ltd Avatar asked Aug 12 '11 17:08

ltd


People also ask

What is backbone JS?

Backbone.js. Backbone.js gives structure to web applications by providing models with key-value binding and custom events, collections with a rich API of enumerable functions, views with declarative event handling, and connects it all to your existing API over a RESTful JSON interface. The project is hosted on GitHub , ...

What happened to model validation in backbone?

A "route" event is triggered on the router in addition to being fired on Backbone.history . Model validation is now only enforced by default in Model#save and no longer enforced by default upon construction or in Model#set, unless the {validate:true} option is passed. View#make has been removed.

What is the use of save model in backbone?

The Backbone.js save model is used to save the data of the model by delegating the sync() method. It reads and saves the model every time when it is called. Syntax: attributes: It is used to define the property of a model. options: It accepts parameters like id, name etc. which are used for a model.

What is the use of backbone in backend?

Backbone.js Backbone.js gives structure to web applications by providing models with key-value binding and custom events, collections with a rich API of enumerable functions, views with declarative event handling, and connects it all to your existing API over a RESTful JSON interface.


2 Answers

Backbone.Model.set won't perform validation if you pass in { silent: true }, and fetch will pass any options through to set, so you could either override fetch or write your own fetchSilent method that passes that in an options object.

However, you might run into a slight gotcha with Backbone.Collection.fetch, because when it receives attributes from the server, it doesn't create the new models with set. Instead, it creates a new model with model = new this.model(attrs, {collection: this}); and then performs validation if there's a validate method on the object.

This is a little annoying. You can get around it by defining a parse method on your collection (if you're using one) that creates a model silently (using {silent: true}), because when Backbone.Collection.add receives a fully formed Backbone model, it won't run the validation. (see the _add and _prepareModel methods in the annotated source).

It's a little annoying that the collection works that way, but (for now at least) it is what it is.

like image 83
satchmorun Avatar answered Nov 04 '22 00:11

satchmorun


Instead of overriding fetch you can do another thing:

When you validate your model, check for model.silent and only validate if that doesn't exist.

So you do the following when you want to fetch a model:

var test = new MyModel({ id: '123', silent: true }); 

// in your Model validate function
validate: function(attrs) {
  if (!attrs.silent) {
    // validate logic here
  }
}

Then you can fetch the model. After you get your model you can unset silent, for future validation.

like image 42
alessioalex Avatar answered Nov 04 '22 00:11

alessioalex