Greg Blass
Greg Blass

Reputation: 3660

Rails 4: Turbolinks redirect with flash

Lets say I have a standard controller create action:

def create
  @object = Object.new(object_params)
  if @object.save
    redirect_to @object, flash: {success: "Created object successfully."}
  else
    render :new
  end
end

Now if I change the redirect to use turbolinks:

redirect_to @object, turbolinks: true, flash: {success: "Created object successfully."}

the server returns a text/javascript response, and my browser is displaying it as a white page with just this line of text on it:

Turbolinks.visit('http:/localhost:3000/objects/1');

How do I make it so my browser actually executes that code instead of displaying it as text?

Also, how can I get the flash success message to appear?

Upvotes: 2

Views: 3299

Answers (2)

Greg Blass
Greg Blass

Reputation: 3660

This is how I ended up solving this using Turbolinks and materialize toasts for a great flash UX:

In my controller:

format.js {
  flash[:toast] = 'Created record successfully.'
  render :create
}

In create.js.erb:

Turbolinks.visit("<%= success_path %>");

In my _flash.html.erb partial:

<% flash.each do |type, message| %>
  <% if type == "toast" %>
    <script id="toast">
      $(function() {
        Materialize.toast('<%= message %>', 3000);
      });
    </script>
  <% elsif type == "success" %>
    ...
  <% elsif type == "alert" %>
    ... 
  <% end %>
<% end %>

Upvotes: 2

Jay-Ar Polidario
Jay-Ar Polidario

Reputation: 6603

This is not a direct answer to your question. But I would suggest using unobtrusive JS for this. You'd want to add remote: true in your form first.

def create
  @object = Object.new(object_params)
  if @object.save
    flash.now.success = 'Created object successfully.'
  else
    flash.now.alert = @object.errors.full_messages.to_sentence
  end
  render :js
end

Create a file create.js.erb containing only the following:

$('#flash').replaceWith("<%= j render partial: 'layouts/flash' %>");
  • This is what render :js will be rendered back to the browser, thereby executing a script that will replace your flash container (#flash or whatever id you used) with the new flash messages
  • Furthermore make sure that you have a partial view file app/layouts/_flash.html.erb which contains your flash HTML code.

Update:

If not using Unobtrusive JS. You can render the partial file like the following:

def create
  @object = Object.new(object_params)
  if @object.save
    flash.now.success = 'Created object successfully.'
  else
    flash.now.alert = @object.errors.full_messages.to_sentence
  end
  render partial: 'layouts/flash'
end

Then in your HTML, you embed something like the following:

$('#myForm').ajaxForm({
    url : '<%= url_for objects_path %>',
    type: 'post',
    dataType : 'json',
    success : function (response) {
        $('#flash').replaceWith(response);
    }
});

P.S. You might also be interested with Wiselinks which actually does this already (partial view loading; you specify the target container to be replaced). Because currently turbolinks do not have support yet with partial loading, it always loads the whole body.

Upvotes: 3

Related Questions