Changing from Prototype to Jquery
For default Rails implements ajax requests with prototype, we need to change it to work with jquery.First, download the rails.js equivalent with jquery from github Copy the rails.js under the src folder to your public/javascripts/.In our layout "application.html.erb" we'll change the next lines
<%= javascript_include_tag :defaults %>
<%= csrf_meta_tag %>
to
<%= javascript_include_tag 'http://ajax.googleapis.com/ajax/libs/jquery/1.4.2/jquery.min.js' %>
<%= javascript_include_tag 'rails' %>
It's time to the ajax magic
Keep it simple, let's think about what we want:
So let's start changing everything again.
The template(layout) need to contain a div to show the flash_notice:
<body>
<div id="container">
<div id="flash_notice" style="display:none"></div>
<%= content_tag :h1, yield(:title) if show_title? %>
<%= yield %>
</div>
</body>
Put some partials in our index and add the remote => true in our links and forms:
<% title "Posts" %>
<div id="post_form"><%= render :partial => 'form' %></div>
<div id="posts_list"><%= render :partial => "posts" %></div>
/views/posts/_form.html.erb
I also put a div to show the errors here, so we can change it in our js responses:
<%= form_for(@post, :remote => true) do |f| %>
<div id= "post_errors" style="display:none"></div>
<p>
<%= f.label :title %><br />
<%= f.text_field :title %>
</p>
<p>
<%= f.label :content %><br />
<%= f.text_area :content, :rows => 5 %>
</p>
<p><%= f.submit %></p>
<% end %>
/views/posts/_posts.html.erb
I created this partial so i can update the list of posts with javascript too:
<table>
<tr>
<th>Title</th>
<th>Content</th>
</tr>
<% for post in @posts %>
<tr>
<td><%= post.title %></td>
<td><%= post.content %></td>
<td><%= link_to "Edit", edit_post_path(post), :remote => true %></td>
<td><%= link_to "Destroy", post, :remote => true, :confirm => 'Are you sure?', :method => :delete %></td>
</tr>
<% end %>
</table>
We need to change our controller too. Since we gonna make a 100% ajax CRUD we don't need that redirects anymore:
class PostsController < ApplicationController
before_filter :load
def load
@posts = Post.all
@post = Post.new
end
def index
end
def create
@post = Post.new(params[:post])
if @post.save
flash[:notice] = "Successfully created post."
@posts = Post.all
end
end
def edit
@post = Post.find(params[:id])
end
def update
@post = Post.find(params[:id])
if @post.update_attributes(params[:post])
flash[:notice] = "Successfully updated post."
@posts = Post.all
end
end
def destroy
@post = Post.find(params[:id])
@post.destroy
flash[:notice] = "Successfully destroyed post."
@posts = Post.all
end
end
Almost there. If you try to use the form now, nothing happens right? If you take a look at the console(server) you will find some errors telling you Rails can't find the view js to render. So let's create this files. Basically we gonna create a view to render javascript, with this javascript we gonna inject or modify our html. We are using jquery to do the modification/injection part, so if you never work with that take a look at the official site to learn a lot of cool stuffs: http://www.jquery.com We need files to create, edit, update and destroy actions, so let's create them:
/views/posts/create.js.erb
Here we verify if the @post object contains errors and changes the behavior according to that:
<% if @post.errors.any? -%>
/*Hide the flash notice div*/
$("#flash_notice").hide(300);
*/Update the html of the div post_errors with the new one*/
$("#post_errors").html("<%= escape_javascript(error_messages_for(@post))%>");
*/Show the div post_errors*/
$("#post_errors").show(300);
<% else -%>
*/Hide the div post_errors*/
$("#post_errors").hide(300);
*/Update the html of the div flash_notice with the new one*/
$("#flash_notice").html("<%= escape_javascript(flash[:notice])%>");
*/Show the flash_notice div*/
$("#flash_notice").show(300);
*/Clear the entire form*/
$(":input:not(input[type=submit])").val("");
*/Replace the html of the div post_lists with the updated new one*/
$("#posts_list").html("<%= escape_javascript( render(:partial => "posts") ) %>");
<% end -%>
/views/posts/edit.js.erb
In this action we just need to update the form with the select post.
$("#post_form").html("<%= escape_javascript(render(:partial => "form"))%>");
/views/posts/update.js.erb
<% if @post.errors.any? -%>
$("#flash_notice").hide(300);
$("#post_errors").html("<%= escape_javascript(error_messages_for(@post))%>");
$("#post_errors").show(300);
<% else -%>
$("#post_errors").hide(300);
$("#flash_notice").html("<%= escape_javascript(flash[:notice])%>");
$("#flash_notice").show(300);
$(":input:not(input[type=submit])").val("");
$("#posts_list").html("<%= escape_javascript( render(:partial => "posts") ) %>");
<% end -%>
/views/posts/destroy.js.erb