如何根据链接点击动态填充部分?

时间:2015-09-30 10:51:53

标签: javascript jquery ruby-on-rails ruby-on-rails-4

所以我有一个名为_node.html.erb的部分。在我的应用程序中,它在不同的视图(以及来自不同的控制器)中呈现。在一个特定的视图中,我会生成一个可链接(和唯一)的events列表。

我想要发生的是,每当有人点击其中一个链接时,它会显示部分并使用正确的信息填充它。我最初尝试这样做的方法是将data-attributes从链接传递给一些更新部分的JS。当我们到达node.comments时,这会快速进入隔离墙,其中部分内容应加载与正在呈现的node相关联的所有评论。

例如,以下是我的_node.html.erb可能的示例代码:

  <!-- Card Meta -->
  <div class="card__meta">
    <aside>
      <%= image_tag node.user.avatar.url, class: "card__author-avatar", alt: "" %>
    </aside>
    <section>
      <h6 class="card__author-name"><%= node.user.name %></h6>
      <time class="card__date"><%= node.created_at.strftime("%B %d, %Y") %></time>
      <p class="card__description"><%= node.media.try(:description) %> 
      <textarea class="card-form__description" name="" id="" cols="30" rows="10">Aenean lacinia bibendum nulla sed consectetur.</textarea>
    </section>

  </div>
  <!-- End Card Meta -->

  <!-- Card Comments -->
  <div class="card-comments-container">
    <h4 class="card-comments__title"><%= pluralize(node.comments_count, "Comment") %></h4>
    <a class="card-comments__button"><i class="icon-arrow-down"></i></a>

    <div class="card-comments">
      <%= render partial: "nodes/comment", collection: node.comments.includes(:user).order(created_at: :desc) %>
    </div>
  </div>
  <!-- End Card Comments -->

以下是用户可以按的链接示例,或者更确切地说是生成链接的Rails代码:

<div class="item-wrapper">
  <div class="item_comment">
    <h5 class="item_comment-title"><%= event.action %> on <%= link_to event.eventable.node.name, "#", data: {toggle_card: "", card_id: event.eventable.node.id, card_title: event.eventable.node.media.title, card_description: event.eventable.node.media.description, card_time: event.eventable.node.media.created_at, card_comments: event.eventable.node.comments_count, card_favorites: event.eventable.node.cached_votes_total } %></h5>
    <p class="item_comment-text"><%= event.eventable.message %></p>
  </div>
</div>

这是我最初使用的jQuery类型的一个例子:

$(document).ready(function() {
  var overlay  = $('.card-overlay'),
      $card     = overlay.find('.card'),
      triggers =  $('a[data-toggle-card]');

  overlay.hide();

  overlay.click(function(e) {
    if( e.target != this ) {

    } else {
      overlay.hide();
    }
  });

  triggers.click(function() {
    var trigger = $(this);
    var tr = trigger;

    overlay.show();

    var card = {
      id: tr.data('card-id'),
      title: tr.data('card-title'),
      description: tr.data('card-description'),
      time: tr.data('card-time'),
      comments: tr.data('card-comments'),
      favorites: tr.data('card-favorites'),
    };

    $card.attr('id', 'card-' + card.id);
    $card.find('.card__content').attr('style', 'background-image: url(' + card.image + ')');
    $card.find('.card__favorite-count').html('<i class="icon-heart"></i> ' + card.favorites);
    $card.find('.card__comment-count').html('<i class="icon-speech-bubble-1"></i> ' + card.comments);
    $card.find('.card__title').text(card.title);
    $card.find('.card__date').text(card.time);
    $card.find('.card__description').text(card.description);
    $card.find('textarea').attr('id', 'card-input-field-' + card.id);


    var player = videojs("example_video_" + card.id, {}, function() {});

    player.src(
      {
        src: card.video.mp4, type: 'video/mp4'
      },
      {
        src: card.video.webm, type: 'video/webm'
      },
      {
        src: card.video.ogv, type: 'video/ogv'
      }
    );
    player.load();

    player.ready(function() {
        console.log("READY")
    });
    return false;
  });
});

如何在不依赖太多JS / jQuery的情况下以更“Railsy”的方式执行此操作?

修改1

在尝试Rich Peck的建议后,我收到了这个错误:

05:46:31 web.1              | Unexpected error while processing request: JS, accepted HTTP methods are OPTIONS, GET, HEAD, POST, PUT, DELETE, TRACE, CONNECT, PROPFIND, PROPPATCH, MKCOL, COPY, MOVE, LOCK, UNLOCK, VERSION-CONTROL, REPORT, CHECKOUT, CHECKIN, UNCHECKOUT, MKWORKSPACE, UPDATE, LABEL, MERGE, BASELINE-CONTROL, MKACTIVITY, ORDERPATCH, ACL, SEARCH, and PATCH

要清楚,这就是我所做的:

修改了我的路线:

  resources :events do
    get :node, action: :node
  end

然后在我的EventsController中创建了一个名为node的动作,如下所示:

  def node
    @node = current_user.nodes.find(params: [node_id])
    respond_to do |format|
      format.js
    end
  end

然后我创建了一个app/views/events/node.js.erb,看起来像这样:

$overlay = $('.card-overlay');
$node = $('<%= j render "nodes/node", locals: {node: @node} %>');
$overlay.append($node);

然后我修改了link_to标签,如下所示:

<%= link_to event.eventable.node.name, event_node_path(event.eventable.node), remote: true, method: :js  %></h5>

2 个答案:

答案 0 :(得分:1)

您需要向服务器发出AJAX请求,然后使用js.erb部分将可能要求的内容返回给前端。这是最多&#39; Rails-y&#39;我能想到的方式。

就个人而言,我要求使用JSON,然后使用一些jQuery来回复返回值,就像在您的示例中所做的那样。通过呼叫后端是你能够获得相关记录的唯一理智方式,.comments位,我相信你会被困在哪里,如果我有的话理解你的问题。

编辑:

This是关于如何使用Rails实现AJAX-y的相当好的教程,以防你过去没有太多理由这样做。

答案 1 :(得分:1)

好的,这里有两个问题:

  1. 你正试图加载&amp;填充部分没有任何额外数据(IE node.comments

  2. 其次,您非常依赖JQuery来更新页面上的各种属性。虽然这本身没有任何问题,但如果您想要更改页面布局等, 会成为问题。

  3. 执行此操作的更“困难”的方法是直接从服务器远程加载节点,就像推荐Alex Lynham一样:

    #config/routes.rb
    resources :cards do
       get :node_id, action: :node #-> url.com/cards/:card_id/:node_id
    end
    
    #app/controllers/cards_controller.rb
    class CardsController < ApplicationController
       def node
          @card = Card.find params[:card_id]
          @node = @card.nodes.find params[:node_id]
          respond_to do |format|
             format.js #-> app/views/cards/node.js.erb
          end
       end
    end
    
    #app/views/cards/node.js.erb
    $node = $("<%=j render "cards/node", locals: {node: @node} %>")
    $('body').append($node);
    
    #app/views/cards/index.html.erb
    <% @cards.each do |card| %>
       <%= link_to card.name, card_node_path(@card), remote: true, format: :js %>
    <% end %>
    

    这将使代码清晰简洁。

    您可以将所有选项直接放在_node.js.erb部分中。虽然它仍然意味着你必须做出一些改变,它会让你能够改变你的部分和没有你现在拥有的所有JQuery专业化的实现。