Showing posts with label JQuery. Show all posts
Showing posts with label JQuery. Show all posts

Thursday, March 25, 2010

JQuery and Unobtrusive Javascript on Rails 3

In the earlier post, JQuery on Rails 3. You will need a few files to kick start in using JQuery.
  1. rails.js from http://github.com/rails/jquery-ujs
  2. jquery.js from http://code.jquery.com/jquery-1.4.2.js
  3. application.js having your custom javascript command
  4. Load them in the layout file
Lets try adding an ajax link somewhere on a page. Notice the difference, we are no longer using link_to_remote anymore. We will instead be using link_to, passing in the :remote key.
index.html.erb

<span id=\"ajax_button\"><%= link_to \'ajax!\', \'/\', :remote => true %></span>

<div id =\'ajax\'>
</div>

What Rails 3 gives us in doing this. If you take a look at the html source file, we get a clean ajax request link in line with html5.

Then we will throw in some trivial JQuery codes into a generic application.js file. We will specify the span id of ajax_button to change the html content of a div id of ajax to have "lol" when the link is clicked.
application.js
$(document).ready(function(){
$("#ajax_button").click(function(){
$("#ajax").html("lol");
});
});


When done right, we should see an update on div id ajax.

In the next example, we are going to do some ajax together with Rails controller request.

For this example, a controller file, posts_controller.rb. We will add a format.js under the respond_to so the method knows that it should format a javascript file.

def create
@post = Post.new(params[:post])
respond_to do |format|
if @post.save
format.html { redirect_to(@post, :notice => 'Post was successfully created.') }
#format.xml { render :xml => @post, :status => :created, :location => @post }
format.js
else
format.html { render :action => "new" }
format.xml { render :xml => @post.errors, :status => :unprocessable_entity }
end
end
end


Then the same is true for forms in Rails 3, when we wanna send an ajax request, the remote_form_for has been scrapped and we will use form_for(@post, :remote => true), again passing in the remote key.
new.html.erb

<% form_for(@post, :remote => true) do |f| %>
<%= f.error_messages %>

<div class=\"field\">
<%= f.label :title %><br />
<%= f.text_field :title %>
</div>
<div class=\"actions\">
<%= f.submit %>
</div>
<% end %>

Then we will create another file in the View folder, create.js.erb which holds the JQuery logic that we want it to run when the create method is fired.
create.js.erb
$("#ajaxified").html(""); // updates the div id ajaxified
alert("Ajax works!"); // prints an alert message
It should print a message and update the ajaxified id with the post title when the form is submitted!

Thursday, September 3, 2009

JQuery on Rails

I am starting to test out JQuery on Rails and see if i can reproduce the same result of what i did back then with the Rails bundled Prototype helpers.

in rjs, (js.rjs)

page.replace_html "widget-count-#{@post.id}", :partial => 'widget_count', :locals => {:post => @post}
page.replace "widget-button-#{@post.id}", image_tag('wiggy.png')

in jquery, (js.erb)

$("#widget-count-<%= @post.id %>").replaceWith
('<%= escape_javascript(render(:partial => 'widget_count', :locals => {:post => @post} ))%>');
$("#widget-button-<%= @post.id %>").replaceWith
('<%= image_tag('wiggy.png') %>');


in addition to that, if you are using JQuery, do not forget to import that JQuery javascript file.

However, if you are dealing with ajax request... there is something extra you need to do. Based on RyanB's railscast at http://railscasts.com/episodes/136-jquery,

in application.js

#to request for js format by default instead of html if you have both respond_to |format|

jQuery.ajaxSetup({
'beforeSend' : function(xhr) {xhr.setRequestHeader("Accept", "text/javascript")}
})


#Changing the behavior of the form, note the form id "new_comment" to submit an ajax request

$(document).ready(function(){
$("#new_comment").submit(function(){
$.post($(this).attr("action"), $(this).serialize(), null, "script");
return false
})
})


JQuery.js has to be loaded first before application.js in order to get it work.

Then for the appearance of the comment in an ajax manner,

in rjs, (js.rjs)

if @comment.save
page.insert_html :top,"comments", :partial => 'comment'


in jquery, (js.erb)

<% if @comment.save %>
$("#comments").prepend("<%= escape_javascript(render :partial => 'comment') %>")
<% end %>


Finally if you intend to use JQuery with other Javascript libraries, Prototype for example, bear in mind the need to declare noconflict. http://docs.jquery.com/Using_jQuery_with_Other_Libraries

One of the example to prevent conflict between JQuery and Prototype is by,

Add this right after the libraries are loaded. Perhaps in application.js

jQuery.noConflict();

Then anytime you intend to use JQuery libraries wrap the JQuery codes inside the jQuery(document).ready(function($){ #jquery codes }) as such,

jQuery(document).ready(function($){
<% if @comment.save %>
$("#comments").prepend("<%= escape_javascript(render :partial => 'comment') %>");
<% else %>
alert('NO!');
<% end %>
})


The $(element) codes without wrapping into jQuery will be treated as Prototype and the score is settled.