Backbone Validate sends a request when validation fails

In accordance with the basic validation documentation, it states:

If validate returns an error, installation and saving will not continue, and model attributes will not be changed.

So, the way I read this set or save should not start if validation fails. But these are not the results that I get. Even when the check fails, it still sends a POST / PUT request. Am I reading documents incorrectly or is something wrong in my code?

Here is my corresponding code: https://gist.github.com/80f6ef0099fbe96025dc

App.Models.Test = Backbone.Model.extend( urlRoot: '/api/test' validate: (attrs) -> errors = [] if attrs.to is '' errors.push name: "to" field: "js-to" message: "You must enter a to address" if attrs.subject is '' errors.push name: "subject" field: "js-subject" message: "You must enter a subject" # Return our errors array if it isn't empty errors if errors.length > 0 ) App.Views.Details = Backbone.View.extend( initialize: -> @model.bind "error", @error, this events: "click #js-save": "saveItem" saveItem: (e) -> e.preventDefault() # Set the model then save it. @model.set subject: $("#js-subject").val() message: $("#js-message").val() mailbox_id: $("#js-from").val() to: $("#js-to").val() cc: $("#js-cc").val() bcc: $("#js-bcc").val() tags: App.Helpers.tagsToObject $('#js-tags').val() scope: $('#js-scope').val() attachments: attachments @model.save null, success: (model, response) => App.Helpers.showAlert "Success!", "Saved Successfully", "alert-success" @next() error: (model, response) -> App.Helpers.showAlert "Error", "An error occurred while trying to save this item", "alert-error" # Show the errors based on validation failure. error: (model, error) -> App.Helpers.displayValidationErrors error 
+4
source share
1 answer

You do this to save your model:

 @model.save null, success: -> ... error: -> ... 

That null is the source of your problem, use {} and everything will start to behave better; if you combine your calls to @model.set and @model.save , everything will be even better:

 attrs = subject: $("#js-subject").val() #... @model.save attrs, success: -> ... error: -> ... 

A save call is as follows:

save model.save([attributes], [options])
[...]
The attribute attribute (as in set ) must contain the attributes that you would like to change

Thus, passing null for attributes means that you want to keep the model as it is.

When you save model, validation is basically saved until set , the code looks like this:

 if (attrs && !this.set(attrs, options.wait ? silentOptions : options)) { return false; } 

Your attrs will be null , so set will not be called; however, if you allow save process your set , you will get the behavior you need. If you passed the wait: true parameter, save would have performed a manual validation on the passed attributes:

 if (options.wait) { if (!this._validate(attrs, options)) return false; ... } 

The _validate internal method is a wrapper for validate that does some bookkeeping and error handling. You are not using wait: true , so this does not apply to you, but I thought it was worth mentioning anyway.

Consider a simple example with a model whose validate always fails. If you say this:

 @model.on 'error', @error @model.save attrs, success: -> console.log 'AJAX success' error: -> console.log 'AJAX error' 

then @error will be @error because save will eventually call set with some attributes and set will call validate . Demo: http://jsfiddle.net/ambiguous/HHQ2N/1/

But if you say:

 @model.save null, ... 

null will skip the set call . Demo: http://jsfiddle.net/ambiguous/6pX2e/ (here AJAX will fail).

Your call to @model.set before @model.save should start your error handler, but if you don't check what @model.set , execution will blindly continue until you call save and talk to your server.


So you have three things:

  • You do not invoke save as it should be.
  • You ignore the return value of @model.set and lose the chance to catch validation errors.
  • Handling database arguments for save(null, ...) might be better, but I don't know if it's worth trying to handle the weird way of calling it.

You should combine your set / save pair only in save or check what set returns.

+5
source

All Articles