Guides section on create.js.erb and the "j" helper over jQuery hooks and ajax callbacks #5573

Closed
wants to merge 3 commits into
from
@@ -1235,3 +1235,105 @@ On pages generated by +NewsController+, you want to hide the top menu and add a
That's it. The News views will use the new layout, hiding the top menu and adding a new right menu inside the "content" div.
There are several ways of getting similar results with different sub-templating schemes using this technique. Note that there is no limit in nesting levels. One can use the +ActionView::render+ method via +render :template => 'layouts/news'+ to base a new layout on the News layout. If you are sure you will not subtemplate the +News+ layout, you can replace the +content_for?(:news_content) ? yield(:news_content) : yield+ with simply +yield+.
+
+
+h3. Rendering in Ajax Forms
+
+There are a lot of situations when we want to submit a form with ajax. Creating a post can be often seen as one of them. Let us see one nice way to create a post without refreshing the entire page:
+
+TIP: jQuery hooks are just fine, but they may grow in complexity. This section covers how to write your ajax requests closer to the MVC structure, so it's easier to maintain:
+
+* +app/assets/javascripts/posts.js+
+
+<erb>
+jQuery('form#new_post').submit(function() {
+ alert('Handler for .submit() called.');
+ $.ajax({
+ type: 'POST',
+ dataType: "JSON",
+ url: url,
+ data: data,
+ success: function(returned_data) {
+ alert('Handles success.');
+ },
+ error: function(returned_data) {
+ alert('Handles failure.');
+ }
+ });
+ return false;
+});
+</erb>
+
+NOTE: Handling JSON is optimized for computers, we'll cover that here too
@vijaydev
vijaydev May 4, 2012 Member

this note is hanging out incoherently. What purpose does it serve?

+
+h4. Optimize for Humans
@vijaydev
vijaydev May 4, 2012 Member

What are we optimizing?

+
+Instead of letting that code lost in some file, a better approach is write it close to the MVC structure. See how it's done in Rails:
+
+* +app/views/posts/_form.html.erb+
+
+<erb>
+<%= form_for @post, :remote=>true do |f| %>
+ <%= f.text_field :body %>
+ <%= f.submit %>
+<% end %>
+</erb>
+
+* +app/controllers/posts_controller.rb+
+
+<erb>
+def create
+ @post = Post.new(params[:post])
+
+ respond_to do |format|
+ if @post.save
+ format.html { redirect_to @post, notice: 'Post was created.' }
+ format.js { } # create.js.erb
+ else
+ format.html { render action: "new" }
+ format.js { } # create.js.erb
+ end
+ end
+end
+</erb>
+
+* +app/views/posts/_post.html.erb+
+
+<erb>
+<div class="post" id="post_<%= @post.id %>">
+ <p><%= @post.body %></p>
+</div>
+</erb>
+
+* +app/views/posts/create.js.erb+
+
+<erb>
+<% if @post.persisted? %>
+ jQuery("form#new_post").clear();
+ alert("Post created with success");
+ jQuery("#posts").append("<%= j render @post %>");
+<% else %>
+ alert("<%= @post.errors.full_messages.to_sentence %>");
+<% end %>
+</erb>
+
+TIP: The +j+ helper escapes special caracters to be used safely in javascript strings
+
+h4. Optimize for Machines
+
+Let's see how to handle JSON values in a very railsy style:
+
+* +app/views/posts/create.js.erb+
+
+<erb>
+<% if @post.persisted? %>
+ //yes, this is a javascript variable
+ var post = <%= @post.to_json %>;
+ alert(post.text);
+ alert("you handle the rendering entirely with javascript now");
+<% else %>
+ //javascript variable again
+ var post_errors = <%= @post.errors.full_messages.to_json %>;
+ alert("ajax callbacks don't seem fun now");
+<% end %>
+</erb>