12

In background, I want it to reload and shows the number how many unread messages are there.
I want that without refreshing page. I mean using ajax.

If I had this in menu, how can I refresh only this section every 30 secs?

<li><%= link_to sanitize('<i class="icon-envelope"></i> ') + "received messages" + sanitize(' <span class="badge badge-info">'+current_user.mailbox.inbox(:read => false).count(:id, :distinct => true).to_s+'</span>'), messages_received_path  %></li>

messages_controller.rb

  def received
    if params[:search]
     @messages = current_user.mailbox.inbox.search_messages(@search).page(params[:page]).per(10)
    else
     @messages = current_user.mailbox.inbox.page(params[:page]).per(10)
    end 
     add_crumb 'Messages Received', messages_received_path

     @box = 'inbox'
     render :index
  end

UPDATE:_______________________________

assets/javascript/refresh_messages_count.js

$(document).ready(function () {
    // will call refreshPartial every 3 seconds
    setInterval(refreshPartial, 3000)

});

function refreshPartial() {
  $.ajax({
    url: "messages/refresh_part";
 })
}

messages_controller.rb

def refresh_part
    @message_count = current_user.mailbox.inbox(:read => false).count(:id, :distinct => true)

    # get whatever data you need to a variable named @data 
    respond_to do |format| 
        format.js {render :action=>"refresh_part.js"} 
    end

end

views/layouts/_menu.html.erb

<span id="message_received_count"><%= render :partial => "layouts/message_received_count" %></span>

views/layouts/_message_received_count.html.erb

<% if user_signed_in? && current_user.mailbox.inbox(:read => false).count(:id, :distinct => true) > 0 %>
 <li><%= link_to sanitize('<i class="icon-envelope"></i> ') + "Received" + sanitize(' <span class="badge badge-info">'+@message_count.to_s+'</span>'), messages_received_path  %></li>
<% else %>
 <li><%= link_to sanitize('<i class="icon-envelope"></i> ') + "Received", messages_received_path  %></li>
<% end %>

views/messages/refresh_part.js.erb

$('#message_received_count').html("#{escape_javascript(render 'layouts/messages_received_count', data: @message_count)}");
thunder
  • 544
  • 5
  • 8
HUSTEN
  • 5,117
  • 4
  • 24
  • 38
  • 1
    Look at this [question], I think it's what you need.[1] [1]: http://stackoverflow.com/questions/11588251/update-a-rails-3-partial-using-ajax-not-a-form – alex Dec 21 '12 at 11:10

3 Answers3

26

You will use setInterval to send the ajax request:

$(document).ready(function () {
    // will call refreshPartial every 3 seconds
    setInterval(refreshPartial, 3000)

});

// calls action refreshing the partial
function refreshPartial() {
  $.ajax({
    url: "whatever_controller/refresh_part"
 })
}

Then you make an action in a controller like this:

def refresh_part
  # get whatever data you need to a variable named @data
  respond_to do |format|
    format.js
  end
end

then you will write a js file named refresh_part.js.haml (you could erb instead of haml).

refresh_part.js.haml would look like this:

$('#part_you_want_to_refresh').html("#{escape_javascript(render 'name_of_partial', data: @data)}");

make sure you set the correct routes in routes.rb.

JP Silvashy
  • 46,977
  • 48
  • 149
  • 227
Khaled
  • 2,101
  • 1
  • 18
  • 26
  • Thanks where should I put the ajax request part to??? should I write that directly to my controller? or do I need to make new file or something??? – HUSTEN Dec 21 '12 at 11:34
  • the jquery part should be in a js file that you include in your view, while the action should be just in a controller. – Khaled Dec 21 '12 at 11:38
  • Yeah, I know. But I'm wondering why did you separate the ajax request and refresh_part.js??? could you please give me an example where to place ajax request at? – HUSTEN Dec 21 '12 at 11:47
  • the refresh_part.js.haml is a file that will be served by the server as a response to the ajax request, it will not be included in the js of the view. Check this cast on Unobtrusive Javascript http://railscasts.com/episodes/205-unobtrusive-javascript?view=asciicast, and this tutorial http://net.tutsplus.com/tutorials/javascript-ajax/using-unobtrusive-javascript-and-ajax-with-rails-3/ – Khaled Dec 21 '12 at 12:16
  • ahhh I got it what you meant! So I have to put the first block of your javascript in the head of layouts/application.html.erb? right?? If so, should I create file separated and render that file in application.html.erb? – HUSTEN Dec 21 '12 at 12:22
  • I mean making js file in assets/javascripts – HUSTEN Dec 21 '12 at 12:24
  • Thanks for response. I'm trying it right now. url: "whatever_controller/refresh_part"; in ajax request should be something like "messages/_received_count.html.erb" ?? – HUSTEN Dec 21 '12 at 13:27
  • I updated my question. I just followed your instruction and tried that codes but now it won't show anything now. and it seems not loading properly. Do you see any problem in my codes? – HUSTEN Dec 21 '12 at 13:53
  • let us [continue this discussion in chat](http://chat.stackoverflow.com/rooms/21526/discussion-between-khaled-and-husten) – Khaled Dec 21 '12 at 15:33
  • nice step-by-step answer, however the semicolon after the url: "string" is incorrect, causes an "unexpected token ; error in javascript console – jpw Feb 12 '15 at 18:10
  • Would you please explain how to set the correct paths inside routes.rb? Thanks. – W.M. May 14 '16 at 21:48
3

FYI, refresh_part.js.erb would look like this:

$("#part").html("<%= escape_javascript(render 'partial', data: @data) %>");

instead of:

$('#part').html("#{escape_javascript(render 'partial', data: @data)}");

also, we can use the alias of "escape_javascript" to simplify this:

$("#part").html("<%= j(render 'partial', data: @data) %>");
Renny Ren
  • 77
  • 1
  • 4
0

Yes you can

<html>
<head>
<script type="text/JavaScript">
<!--
function timedRefresh(timeoutPeriod) {
    setTimeout("location.reload(true);",timeoutPeriod);
}
//   -->
</script>
</head>
<body onload="JavaScript:timedRefresh(5000);">
<p>This page will refresh every 5 seconds. This is because we're using the 'onload' event to call our function. We are passing in the value '5000', which equals 5 seconds.</p>
<p>But hey, try not to annoy your users too much with unnecessary page refreshes every few seconds!</p>
</body>
</html>

Source: http://www.quackit.com/javascript/javascript_refresh_page.cfm

Leroy
  • 11
  • 1