Rails 5的单个页面上的多个Ajax链接

时间:2019-05-02 17:31:46

标签: ruby-on-rails ruby-on-rails-5

我有以下代码:

视图

<% @jobs.each do |job| %>
      <tr>
        <td>
          <div class="job"><%= link_to(job.title, job.url, :target => "_blank") %>
          <a id="add-to-favorites"><i class="fa fa-heart" title="Save to my jobs"></i></a></div>
...

控制器

  def add_to_favorites
    //I would like to see some params here also
    puts "made it to add_to_favorites"
  end 

JS

$("#add-to-favorites").click(function(){
        $.ajax({url: "add_to_favorites",
                        type: "GET",
                        data: {}
                    });
    });

路线

  get 'add_to_favorites', to: 'jobs#add_to_favorites'

两个问题。首先,如何获得每个作业的点击/ ajax调用。现在,它仅适用于页面上的第一个作业。我猜这是由于我对视图中的每个作业都使用了id="add-to-favorites"。这是每个工作的唯一ID吗?

第二,如何将参数传递给控制器​​?

2 个答案:

答案 0 :(得分:1)

您对ID的担心是正确的。您可能应该在元素上包含具有id属性的对象id。您可以执行以下操作:

<%= link_to '#', id: "add-to-favorites-#{job.id}" do %>
  <i class="fa fa-heart" title="Save to my jobs"></i>
<% end %>

...但是这将使得很难通过JavaScript进行定位。您最好这样做:

<%= link_to '#', id: "add-to-favorites-#{job.id}", class: 'some-class', data: {id: job.id} do %>
  <i class="fa fa-heart" title="Save to my jobs"></i>
<% end %>

这样,您可以使用data-id属性获取所需的ID。

$(".some-class").click(function(e){
  e.preventDefault();
  var idToGet = $(this).data('id');
  data = {
    id: idToGet,
    // whatever else you need to pass to your controller as params
  };

  $.ajax({
    url: "add_to_favorites",
    type: "GET",
    data: data
  });
});

您以data身份通过的所有内容都应以params身份出现在您的控制器中。同样,通常将这类事情配置为使用POST请求。

答案 1 :(得分:1)

  

这是每个工作的唯一ID吗?

是的。根据定义,页面上只有给定id的一个元素。我想我会做更多的事情:

<% @jobs.each do |job| %>
      <tr>
        <td>
          <div class="job">
            <%= link_to(job.title, job.url, :target => "_blank") %>
            <i class="fa fa-heart add-to-favorites-icon" data-id="<%= job.id %>" title="Save to my jobs"></i>
          </div>
...

自从我使用erb已经很久了,所以您可能需要弄弄它来正确设置data-id。我已删除了a元素,因为它似乎不是必需的。

然后,我想我将您的routes.rb更改为更像:

resources :jobs do 
  member do 
    post :add_to_favorites
  end
end

我认为使用POST HTTP动词执行此操作更为常规,因为它不是幂等的。这将为您提供:

add_to_favorites_job POST   /jobs/:id/add_to_favorites(.:format)      jobs#add_to_favorites
                jobs GET    /jobs(.:format)                           jobs#index
                     POST   /jobs(.:format)                           jobs#create
             new_job GET    /jobs/new(.:format)                       jobs#new
            edit_job GET    /jobs/:id/edit(.:format)                  jobs#edit
                 job GET    /jobs/:id(.:format)                       jobs#show
                     PATCH  /jobs/:id(.:format)                       jobs#update
                     PUT    /jobs/:id(.:format)                       jobs#update
                     DELETE /jobs/:id(.:format)                       jobs#destroy

然后,我将您的js更改为更像:

$(".add-to-favorites-icon").click(function(){
  $.ajax({
    url: "jobs/#{$(this).data().id}/add_to_favorites",
    type: "POST",
    data: {}
  });
});

您可能需要摆弄一下。

$(this)将引用所单击的图标,而$(this).data().id应返回上面设置的id。字符串插值可为您提供一个类似于jobs/1/add_to_favorites的网址(或任何id是)。然后,单击该图标将进行POST调用,该调用将通过add_to_favorites参数路由到您的id操作,您可以使用它来查找job

  

如何将参数传递给控制器​​?

要将参数传递给控制器​​,请在data调用中使用$.ajax参数。像这样:

$(".add-to-favorites-icon").click(function(){
  $.ajax({
    url: "jobs/#{$(this).data().id}/add_to_favorites",
    type: "POST",
    data: {
      foo: 'bar'
    }
  });
});

这将进行POST调用,该调用将通过add_to_favorites参数和id参数路由到您的foo操作。

现在,在我看来,您可能希望将喜欢的图标用作拨动开关。也就是说,如果某人尚未收藏该工作,则单击该图标会将其添加为收藏。并且,如果某人喜欢该工作,则单击该工作将使该工作不受欢迎。因此,您可以执行以下操作:

<% @jobs.each do |job| %>
      <tr>
        <td>
          <div class="job">
            <%= link_to(job.title, job.url, :target => "_blank") %>
            <i class="fa fa-heart <%= current_user.favorited_jobs.include?(job) ? 'favorited' : 'not-favorited' %>" data-id="<%= job.id %>" title="Save to my jobs"></i>
          </div>
...

(自然地,您假设您可以做类似current_user.favorited_jobs.include?(job)的事情,您可能必须创建它。这只是一个示例。)

然后,您可以使用“收藏”和“未收藏”类来更改css中的图标颜色,以便用户获得有关他们已收藏的内容的视觉反馈。

然后将routes.rb更改为:

resources :jobs do 
  member do 
    post :add_to_favorites
    post :remove_from_favorites
  end
end

然后将您的js更改为以下内容:

$(".job .not-favorited").click(function(){
  $.ajax({
    url: "jobs/#{$(this).data().id}/add_to_favorites",
    type: "POST",
    data: {}
  })
  .done(function(){
    $(this).removeClass('not-favorited').addClass('favorited')
  });
});

$(".job .favorited").click(function(){
  $.ajax({
    url: "jobs/#{$(this).data().id}/remove_from_favorites",
    type: "POST",
    data: {}
  })
  .done(function(){
    $(this).removeClass('favorited').addClass('not-favorited')
  });
});

现在,单击图标既可以更改模型中的收藏状态,也可以更改前端的图标颜色(假设您已经用css了)。