Showing posts with label Ajax. Show all posts
Showing posts with label Ajax. 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!

Tuesday, February 23, 2010

JQuery on Rails 3.0

Firstly, head over to http://github.com/rails/jquery-ujs and obtain the rails.js file and substitute with the one in our javascript folder.

We will then include the required javascript files,

<%= javascript_include_tag 'jquery','rails','application' %>

Get the jquery.js file from http://code.jquery.com/jquery-1.4.2.js

Now... let's do some trivial testing so that we know JQuery is actually working.


class EntriesController < ApplicationController
respond_to :html, :xml, :js

def index
@entries = Entry.all_entries
respond_with(@entries);
end

def new
@entry = Entry.new
end

def create
@entry = Entry.new(params[:entry])
if @entry.save
respond_with(@entry, :location => entries_path)
end

end

end


We will then create a create.js.erb file which contains the JQuery code that we want to run when then action is invoked.
Let's put something like,
alert("Thanks for visiting!");

The new syntax in Rails 3 is that we will not use remote_form_for no more, but instead

<% form_for @entry, :remote => true do |f| -%>
<%= f.error_messages %>
<%= f.label :title, "Title" %>
<%= f.text_field :title %>


Same is true if it's a link,

<%= link_to 'Ajaxified', :remote => true %>

If done right, the browser should fire an Alert box 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.