简体   繁体   中英

Rails - why isn't ajax sending params to GET request

I am trying to send data through a get request using ajax but the param doesn't seem to be getting sent. I have a page that shows a random item from the db. You get to this page from a link in the navbar. Once on this page there is a link that allows you to skip the current item to find another random item making sure the next item isn't the one the user was just viewing.

routes.rb

get 'pending', to: 'items#pending'

view

<%= link_to 'Skip', '', class: "btn btn-default btn-xs",
                     id: "skip-btn",
                     :'data-item-id' => @pending_item.id %>

controller

def pending
    @previous_pending_item_id = params[:id] || 0
    @pending_items = Item.pending.where("items.id != ?", @previous_pending_item_id)
    @pending_item = @pending_items.offset(rand @pending_items.count).first
    respond_to do |format|
      format.js
      format.html
    end
  end

I have respond to both html and js because I am using the action for the navbar link as well as the link on the page. The link on the page is the skip button which should bring up another random item.

sitewide.js.erb

  $('#skip-btn').on('click', function () {
    $.ajax({
      data: {id: $(this).data("item-id")},
      url: "/pending"
    });
  });

When I look in the server log is says Started GET "/pending"... but doesn't make any mention of a param being sent. What am I missing?

The reason I'm using ajax for this is because I don't want the param showing in the url.

For clarification I need the url when visiting this page to always be /pending with no params or additional :id identified in the url. This page should always show a random record form the db. The only reason I need to send a param is to make sure no record is every repeated consecutively even though they are random.

I think you need to prevent default link action:

  $('#skip-btn').on('click', function (event) {
    event.preventDefault();
    ...
  });

While you can do it the way you're attempting, I think it's worth pointing out that sending data in a GET request is a bit of an antipattern. So why not doing it the "correct" way!

Change your routes.rb to:

get 'pending/:id', to: 'items#pending'

and change sitewide.js.erb to:

$('#skip-btn').on('click', function () {
    $.ajax({
      url: "/pending/" + $(this).data("item-id")
    });
  });

I'd like you to check for the format its sending the the query to your controller. And the type of format you want to receive at the front end.

$('#skip-btn').on('click', function (e) {
  e.preventDefault();
  $.ajax({
    dataType: 'json', //This will ensure we are receiving a specific formatted response
    data: {id: $(this).data("item-id")},
    url: "/pending"
  });
});

In your controller maybe you want to pass it back as a json object.

def pending
  #@previous_pending_item_id = params[:id] || 0
  #No need to make it an instance variable
  previous_pending_item_id = params[:id] || 0

  #Same goes for pending_items. No need to make it a instance variable, unless you're using it somewhere else.
  pending_items = Item.pending.where("items.id != ?", previous_pending_item_id)
  @pending_item = pending_items.offset(rand pending_items.count).first
  respond_to do |format|
    format.js
    format.html
    format.json { render json: @pending_item.as_json }
  end
end

So that you can take value from response and append it to your page.

Similarly if you are expecting a js or html response back, you should mention that in your ajax call. Let me know if it does help you resolve your issue.

Update:

Let's say in your page, it shows the data of @pending_item object in a div,

<div id="pending_item">...</div>

When you're making a ajax request to your controller you want div#pending_item to show the a new random pending_item.

$('#skip-btn').on('click', function (e) {
  e.preventDefault();
  $.ajax({
    dataType: 'html', //we'll receive a html partial from server
    data: {id: $(this).data("item-id")},
    url: "/pending",
    success: function(res){
      //We'll set the html of our div to the response html we got
      $("#pending_item").html(res);
    }
  });
});

In your controller you do something like:

format.html { render partial: 'pending_item', layout: false }

And in your partial file "_pendint_item.html.erb" you'll access your instance variable @pending_item and display data

This will send the response to server as html, and there you'll only set your div's html to this.

Update 2

Your partial might look like this, or just however you want to display your pending item. The thing to know is it will be accessing the same instance variable @pending_item you have defined in your controller's method, unless you pass locals to it.

<div class="pending_item">
  <h3><%= @pending_item.name %></h3>
  <p><%= @pending_item.description %></p>
</div>

I suggest you do a console.log(res) in the success callback of your ajax call to see what you're getting back from server.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM