powmedia / backbone-forms

Form framework for BackboneJS with nested forms, editable lists and validation
MIT License
2.17k stars 415 forks source link

Adding server side errors to backbone-forms #110

Open ryana opened 12 years ago

ryana commented 12 years ago

It's fairly easy to pass server side errors through backbone-forms. If we patch the Form initialize() to do something like this:

--- a/src/form.js
+++ b/src/form.js
@@ -57,6 +57,11 @@ var Form = (function() {
       //Store main attributes
       this.options = options;
       this.model = options.model;
+
+      if (this.model && this.options.onError) {
+        this.model.on('error', options.onError.bind(this));
+      }
+
       this.data = options.data;
       this.fields = {};

Then it's just dom manipulation when an error hits the model. We could also make an options.modelCallbacks object to arbitrarily bind methods to any event on the model instead of just onError. Here's some coffeescript from something I hacked together that handles errors on base as well:

  onError: (model, collection) ->
    errors = jQuery.parseJSON(collection.responseText)
    form = this.$el
    base = form.find('.base-errors')
    if base.length == 0
      base = $('<div class="base-errors alert alert-error"></div>')
      form.prepend(base)

    for field of errors
      id = '#' + model.cid + '_' + field
      control_group = $(id).parents('.control-group')

      if control_group.length > 0 
        control_group.addClass('error').
          find('.help-block').
          html(errors[field].join(', '))
      else if field == 'base'
        base.html(base.html() + '<p>' + errors[field].join('<br>') + '</p>')
      else
        base.html(base.html() + '<p>' + field + ': ' + errors[field].join(', ') + '</p>')

Disclaimer: this is my first time using Backbone extensively in a project, so I could be missing some bigger picture functionality or theme. If I am, feel free to put me in my place :)

philwo commented 12 years ago

I tried your suggestion as I needed it for my project and it works fine. Thank you very much! It's very helpful in combination with something like Django, because that already handles model validation on the server (where it belongs, IMHO).

nicolaskern commented 9 years ago

This is exactly what I'm looking for, but I can't make it work for the latest version, did anyone manage to make it work?

Best, Nicolas

ryana commented 9 years ago

I haven't used backbone in a couple years. Sry. Good luck!

nicolaskern commented 9 years ago

I guess I'm getting to something, but I think as well it'd be a nice addition to the plugin, so I might make a pull-request !

nicolaskern commented 9 years ago

Here you go :

Marionette.ItemView = Marionette.ItemView.extend
    onError: (model, collection) ->
      try
        errorsJson = $.parseJSON(collection.responseText)

        if errorsJson
          errors = errorsJson.errors.children

          for field of errors
            if errors[field].errors
              $('.field-' + field).addClass('has-error').find('.help-block[data-error]').html errors[field].errors.join(', ')
      catch e
        return

What do you think ?

ryana commented 9 years ago

I don't know if the "what do you think?" is for me, but I'm so out of the Backbone game that I have no clue anymore :)

nicolaskern commented 9 years ago

It was more to people who might have the same problem as I had :P