Topic: new at ajax, create comments

I have a comment form inside my show view

    <%= form_tag :controller => 'entries' ,:action => 'create_comment', :url => {:entry => @entry}, :remote => true do |f| %>
      <p><h2><%= t(:leave_comment) %></h2></p>

          <p><%= text_area_tag :content, params[:comment],:class => "comment" %></p>
      <p><%= submit_tag "comment", :class => "button" %></p>
    <% end %>

and a method named create_comment to create it, how can I add ajax to this? i add the format.js to show or to create_comment?

Re: new at ajax, create comments

Are you using a javascript framework? Or just straight javascript? Using something like jQuery can greatly simplify the process of ajaxifying forms. Of course, some would argue that using a whole framework to solve just a couple of javascript problems is overkill. I typically do find the presence of a whole framework pretty helpful, so for me it's not so much of an issue, and when I do use javascript I tend to use jQuery because it is just so easy to throw down a bunch of manipulation code and get back to work with th rest of the app. I've done a bunch of jQuery ajax stuff by now, so if you end up going that route and still need help, I'm all ears.

Re: new at ajax, create comments

no, Im not using a framework.


Im trying to use AJAX on my web but I cant get it work

layouts/application.html.erb

    <%= javascript_include_tag :defaults %>
    <%= javascript_include_tag "jquery" %>
    <%= csrf_meta_tag %>

controllers/entries_controller.rb

  def create_comment
    @comment = Comment.new(:content => params[:content], :entry_id =>
params[:entry], :user_id => current_user)
respond_to do |format|
      if @comment.save
        format.html { redirect_to public_entry_path(@comment.entry),
:notice => t(:comment_created) }
        format.xml  { head :ok }
        format.js
      else
        format.html { render :action => 'show', :id => params[:entry] }
        format.xml  { render :xml => @comment.errors, :status =>
:unprocessable_entity }
        format.js
      end
    end
  end

views/entries/create_comment.js.erb

$("comments").prepend("<%= escape_javascript(render('comments')) %>");

views/entries/show.html.erb

<div id="comments">
<p>
<h2 style="color: #222; text-shadow: 0px 2px 3px #555;">Comments</h2>
</p>
<p>
<%= render 'comments' %>
</p>

<% if logged_in? %>
<hr />
  <%= form_tag({:controller => 'entries', :action => 'create_comment',
:entry => @entry.id}, :remote => true) do %>
    <p><h2><%= t(:leave_comment) %></h2></p>
          <p><%= text_area_tag :content, nil, :class => "comment" %></p>
    <p><%= submit_tag "Comentar", :class => "button" %>
    </p>
  <% end %>

<% end %>
</div> <!-- Comments -->

views/entries/_comment.html.erb

  <%  @comments.each do |comment| %>
  <%= comment.content %>
  <% end %>

Everytime I hit on Create comment I get the html response

Last edited by jtomasrl (2011-07-08 00:13:13)

Re: new at ajax, create comments

Well, it looks like you are using a framework, since you are requiring jquery and :defaults. You might want to look at how your app is set up. Are you using rails 3? If so, you can tell it that you want it to use jquery as your default javascript framework (which is what I would do).

Otherwise, you might be getting library interference, as by default rails uses prototype, which namespaces the $ variable to point to itself. jQuery does the same thing, which is what can lead to the interference. However, jquery has a compatibility mode which lets it live side by side with prototype (forget exactly how to do it, but if you google around, you should be able to find it). This lets you assign jQuery to $j (or whatever you want really). This lets you use both prototype (or mootools, or whatever) and jquery next to eachother, though sometimes you'll have to search and replace your way through some jquery plugin to make it use $j instead of $ (even though plugins are supposed to use the longer jQuery namepace to avoid this issue, it's a pain to write the extra 5 character ;-).

Anyway, if you don't need prototype, first make sure that your library is actually loading properly by running some jquery code through a javascript console (either using chrome's developer tools or firebug for firefox).

That having all been said, the way I would approach this (if I were doing it) is to scrap having a create_comment.js.erb. You don't really need that. I would bind the onclick event of the comment submit button to a function which handles the ajaxification of the form (in jquery, you do this with the click function). Inside that function, I would submit the form using an ajax post request. I think you can specify a success callback function which executes assuming that the post works as it should. This callback would then take the posted comment and throw it in a new comment div (or whatever).

Also, since you aren't using the create as the controller action name, I would make sure that you have that action routed properly to the post.

Re: new at ajax, create comments

Jquery is working, but Im not understanding how javascript works and render other pages

Re: new at ajax, create comments

Well, the nice thing about jQuery is that you can select html elements using css selectors, so everything is very sort of standardized (especially if you are using haml, since then you are also creating the html using the same syntax as you are using to style and javascriptify it - very slick way to go in my opinion).

So lets say you have made the post and are just trying to insert the ajax into the page. Suppose furthermore that you have a div with an id of comments and that you want to stick your new comment in there. You might do something like this.

$("div#comments").append("<div class=comment>" + comment_text + "</div>");

That would insert the comment_text value into a div which would go into the comments div. Make sense? Then all you have to do is be able to submit the ajax request and (probably before doing that) grab the value of the comment_text from the val function (http://api.jquery.com/val/), as well as any other information you want to display instantly after submitting the request successfully.

I'm not going to walk you through ever step of which functions to use and such, but seriously you should just check out the api documentation (http://api.jquery.com/). Everything you need is there. If you have more specific questions on how to put the pieces together, let us know.

Re: new at ajax, create comments

great summary and thanks for that links I will check them out
BTW, there was a problem with prototype and jquery, so I delete prototype and installed jquery

Last edited by jtomasrl (2011-07-08 02:59:10)

Re: new at ajax, create comments

Sure thing.

Re: new at ajax, create comments

last thing, if I want to add ajax to a link_to in the show.html.erb, the js file should be named show.js.erb right?

<%= link_to t(:adv_bb), "#?w=500", :rel => "bbadv", :class => "poplight", :remote => true %>


and how can I do for example

if @value == true
# Use format.js
else
# User format.html
end

Last edited by jtomasrl (2011-07-08 13:26:34)

Re: new at ajax, create comments

Like I said, I don't think you really need a .js.erb file for this at all. The only time you really need a js.erb file is if you need to create some on-the-fly-custom javascript, for example, pre populated with some data. An example of this is in the dynamic select menu railscast that Ryan Bates did. He showed how you can use a js.erb file and controller action to populate a javascript file with arrays of state and country (or something like that) so that selecting a country narrows down the possible states available for selection. Here, I really don't think you need to do anything like that. It's definitely a more complicated technique.

Here you really just need to attach a javascript function to your link. To do this, it is slightly more appropriate to use link_to_remote, as it is designed specifically for this purpose. Of course, if you want to make sure that your app is also javascript-off friendly (yes, some people do leave javascript off), then leaving it as link_to and binding the onClick event (through jQuery's click(), or whatever) will only pluck up the functionality and overwrite the default link behavior if javascript is actually enabled. You should put the javascript for your application in your application.js file in public/javascripts, unless you have enough js that you need to separate it out into different files (which you probably won't, at least for some time).

Does that make sense?