Search code examples
ruby-on-railsformtastic

How can I display field validation error messages on formtastic form with :remote => true?


I have a formtastic form like the following:

= semantic_form_for @record, :remote => true, :id => 'my_form', :url => ...

Since I'm using :remote => true, I handle the response from the controller in javascript:

$('#my_form')
  .bind("ajax:beforeSend", function(evt, xhr, settings){

  })
  .bind("ajax:success", function(evt, data, status, xhr){
      $('#response').append(xhr.responseText);
  })
  .bind('ajax:complete', function(evt, xhr, status){

  });

With :remote => false, my form automatically displays field validation errors resulting from trying to save the record in the controller like so:

@record = Record.new(params[:record])
@record.save

How do I make the formtastic field validation errors appear with :remote => true, where I'm handling the response myself in javascript?


Solution

  • Put the formtastic form in a view by itself.

    In the controller action that handles the posted form, you can re-"render" the view when the record save fails. When the view is rendered, formtastic will look at the errors field in @record and display the validation errors. If the save succeeds, you can render an empty string to indicate success. (A more complex response scheme is possible depending on what you need.)

      def save_record
        if request.xhr?               # form submitted using remote => true
          respond_with do |format|
            format.html do
              if @record.save
                # record saved successfully
                render :text => ""    # indicate success with empty response
              else                    # error saving record; send back form with validation errors marked
                render :template => '/path/to/record_form_view', :layout => false
              end
            end
          end
          return
        end
        #...
      end
    

    Then, in the client-side javascript, when the record fails to save, you can replace the existing form with the rendered view passed back from the controller.

    // reference: http://www.alfajango.com/blog/rails-3-remote-links-and-forms/
    function setup_record_form_bindings() {
      $('#record_form_id')
      .bind("ajax:beforeSend", function(evt, xhr, settings){
        var $submitButton = $(this).find('input[name="commit"]');
        $submitButton.get(0).value = "Submitting...";
      })
      .bind("ajax:success", function(evt, data, status, xhr){      
          if (xhr.responseText === "") {              // successful save
                                                      // do somethign appropriate here
          } else {                                    // error saving
            $('#record_form_id').remove();            // remove old form, to replace with form in responseText
            $('#record_form_parent_id').append(xhr.responseText);  // should be the newly rendered form (with validation errors shown)
            setup_record_form_bindings();
          }
      })
      .bind('ajax:complete', function(evt, xhr, status){
      });
    }
    setup_record_form_bindings();