emi
emi

Reputation: 2950

AJAX button on a Rails App

This is my app here: http://mighty-brushlands-6367.herokuapp.com/ It displays jokes chosen randomly from the database. But then I want this to be done by AJAX without refresh. So I'm looking for some help to learn how to do this. This is how the button looks in view. I'm using Twitter Bootstrap.

<div><blockquote class="pull-left">
          <p id="mycontainer"><%= @l.content %> </p>
          <small><%= @l.author %> </small>
          <button class="btn btn-mini", "pull=right" type="button">Następny -></button>

        </blockquote></div>
      </div>

But now I'm quite confused here. Cause I don't really know how to add the code to the button which is inside a bootstrap tag. I check this post Attaching functionality to a button in rails 3 and others on google but they are all dealing with forms and not a button. Any help please? I'm a newbie :D

If it helps my controller looks like this:

class KalendarController < ApplicationController

  def next
    @l = Joke.find_by(id: rand(1..Joke.count))
    #@l = Joke.find_by_id(@l)
  end

  def show
    #random_id = Joke.all.sample
    @l = Joke.find_by(id: rand(1..Joke.count))
    #@l = Joke.find_by_id(@l)

    @t = Time.now.strftime("%A")
    @week = Date.today.cweek % 2 == 0 ? "#{trans} " "PARZYSTY" : "NIEPARZYSTY"
  end


  def trans
    @t = Time.now.strftime("%A")
    if @t == "Monday"
      "Poniedziałek"
    elsif @t == "Tuesday"
      "Wtorek"
    elsif @t == "Wednesday"
      "Środa"
    elsif @t == "Thursday"
      "Czwartek"
    elsif @t == "Friday"
      "Piątek"
    elsif @t == "Saturday"
      "Sobota"
    elsif @t == "Sunday"
      "Niedziela"
    end
  end

  def rnd
    (0..4).to_a.sample
  end


end

Upvotes: 2

Views: 192

Answers (3)

Paul Richter
Paul Richter

Reputation: 11082

Based on the comment thread, I believe the main point to remember is that a GET request made through AJAX is basically no different than a similar request made through the browser. The chief difference is that it does not refresh the entire page (unless your JavaScript does something to that effect), and it is, of course, "asynchronous" so that operations occur outside the normal program flow, and the browser is not locked up. Note that an AJAX request can be made synchronous, but that's another story, and not relevant here.

With that in mind, I'm going to add some more clear ID attributes to your HTML, so that we can easily find them after successfully making our AJAX request (which I will show further below):

<div id="joke_section">
  <blockquote class="pull-left">
    <p class="content_container"><%= @l.content %> </p>
    <small class="author_container"><%= @l.author %> </small>
    <button id="next_joke" class="btn btn-mini", "pull=right" type="button">Następny -></button>
  </blockquote>
</div>

We will then add the onClick to the button (I assume you would have this in the $(document).ready function):

$("#next_joke").click(function(event){
    // ajax request goes here. See below.
})

As I said, since an AJAX request is nearly the same as a regular HTTP request, we can simply point the request's destination URL to some path to which your Rails app will respond. If you have not already done so, you will need something like this in your routes.rb file:

get 'jokes/next' => "kalendar#next"

Note: you can name the URL path as you please, what ultimately matters is which controller#action it points to.

This is the AJAX request using jQuery (there are other ways to fire off AJAX request, I find this the easiest):

$.ajax({
    url: "jokes/next",
    type: "GET", // This is default. Showing it for demonstration purposes.
    dataType: "json" // Tell the server we want to receive a JSON object
    success: function(jokeJson, textStatus, jqXHR){
        $jokeSection = $("#joke_section")

        // Replace container contents with Joke JSON data
        $jokeSection.find("p.content_container").html(jokeJson.content);
        $jokeSection.find("p.author_container").html(jokeJson.author);
    }
});

You can find all you ever want to know about a jQuery AJAX request here. Check it out to learn what options are available, and what they all do. It is definitely worth skimming over, at the very least.

Long story short, the success function is executed if the request returned properly, and as I have written above, we replace the contents of your containers with the elements of the JSON object returned.

Finally, in order to render the JSON requested by your AJAX call, you can simply do this:

def next
    respond_to do |format|
        format.json { render json: Joke.find_by(id: rand(1..Joke.count)) }
    end
end

Note about the respond_to block and the format.json: should ensure that the action responds only to a json request, and returns a 406 Not acceptable for any other format.

Upvotes: 0

Andy Henson
Andy Henson

Reputation: 407

Here is a gist I created showing the pertinent parts of your application to simply use button_to and a js template to update the view

https://gist.github.com/andyh/0c28abb7124fb283a924

The only thing missing is setting the classes on the button itself

Upvotes: 1

Anthony Atkinson
Anthony Atkinson

Reputation: 3248

I don't expect to get the answer on this one because I just wanted to walk you through rewriting your code with a little more refinement on the day-of-the-week stuff:

def trans
  days = ["Niedziela", "Poniedziałek", "Wtorek", "Środa", "Czwartek", "Piątek", "Sobota"]
  @t = Date.today.wday
  days[@t]
end

Upvotes: 1

Related Questions