1

问题描述:

我有一组链接的视图:

<% @feeds.each do |f| %>                
  <div class="feed">
    <span class="feed_counts"> <%= f.display_counts %> </span>
    <%= link_to "refresh", { :controller => 'Feeds', :action => "refresh_feed", :feed_id => f.id}, :remote => true, :class => 'refresh_feed_link' %>
    </div>
<% end %>

用户单击链接并启动下一个控制器方法:

def refresh_feed
  @feed = Feed.find(params[:feed_id])
  @feed.parse
end

现在我想将对应的 span-element 的内容更改为 @feed.total_count 值。

我的尝试:

好吧,据我所知,有两种方法可以在不重新加载整个页面的情况下做到这一点:

方式一:

我可以在我的布局中包含 js:

<%= render :partial => 'shared/partial_js' %>

并在 partial_js 中使用此代码:

<script type="text/javascript">
  $().ready(function() {

    $('.refresh_feed_link').bind('click', function() {
      $(this).closest('.feed').find('span.feed_counts').text('woo');
    });
 });
</script>

在这种情况下,我有 '$(this)' 并且可以找到相应的 'span' 元素。但是我没有任何可能获得我的@feed 变量值。

方式二:

我可以加

respond_to do | format |  
  format.js {render :layout => false}  
end

到我的控制器并创建 refresh_feed.js.erb 文件。在这个 JS 文件中,我可以使用我的变量作为 <% @feed.total_count %>,但我不知道我的多个链接中的哪一个被点击了。换句话说,这个文件中的 $(this) 变量将是 (window) 并且我找不到相应的跨度元素。

问题:

有什么办法可以得到我想要的吗?
提前致谢。

4

1 回答 1

1

有很多方法可以做到这一点。使用您描述的方式,这是“单击哪个链接”问题的简单解决方案:dom_id

1)做一个部分:app/views/feeds/_feed.html.erb

<%= div_for feed do %>
  <span class="feed_counts"> <%= feed.display_counts %> </span>
  <%= link_to "refresh", { :controller => 'Feeds', :action => "refresh_feed", :feed_id => feed.id}, :remote => true, :class => 'refresh_feed_link' %>
<% end %>

2) 在您看来:

<%= render @feeds %>

3) 在您的 refresh_feed.js.erb 文件中:

$('<%= dom_id(@feed) %>').replaceWith('<%= escape_javascript( render @feed ) %>');

还有另一种我个人更喜欢的方式,但我会花一点时间来写它,所以我把这个留在这里给你,同时我写另一种方式。


第二种方式

下面是我的做法,使用 CoffeeScript 和 HAML,因为它们更容易输入。你可以把它转换成普通的 JS 和 ERB,它的工作原理是一样的。

我会像这样设置我的路线:

resources :feeds do
  get "refresh_feed", :on => :member

假设你有一个“饲料”部分,app/views/feeds/_feed.html.haml

= div_for feed, :class => 'feed_widget' do
  %span.feed_counts= f.display_counts
  = link_to "Refresh", refresh_feed_path(f), :class => 'refresh_link'

在任何视图中:

= render @feeds

// or, more explicit:

= render :partial => 'feed/feeds', :collection => @feeds, :as => :feed

现在,在app/assets/javascripts/feeds.js.coffee

# Global Scope for CoffeesScript, ignore for JS
root = exports ? this

# Check page if there are feed widgets on it and initialize a handler for each one.
jQuery ->
  if $('div.feed_widget').length
    $('div.feed_widget').each ->
      new FeedWidget $(this)

root.FeedWidget = (container) ->
  @container = container
  @refresh_link = @container.find('a.refresh_link')
  @feed_counts = @container.find('span.feed_counts')
  this.initialize()

root.FeedWidget.prototype =
  initialize: ->
    self = this
    @feed_counts.click (event) ->
      event.preventDefault()
      $.ajax
        type: 'GET'
        url: self.refresh_link.attr 'href'
        dataType: 'json'
        error: (xhr, status, error) ->
          console.log error
          console.log xhr
        success: (data, status, xhr) ->
          self.feed_counts.text data.feed_counts

然后在你的控制器中:

def refresh_feed
  @feed = Feed.find(params[:id]) #assuming you have a resourceful route to this.
  @feed.parse
  respond_to do |format|
    format.js { render :json => { feed_counts: @feed.counts }, :status => :ok } # use whatever method gets you the feed count here.
  end
end

现在您得到一个 JSON 响应,它只是提要计数,并且您有一个 JS 侦听器/处理程序小部件,它将自动显示(和功能)并放置您呈现的部分。酷吧?

注意,上面的代码没有经过测试,因为我没有你的应用程序,所以你必须根据你的需要对其进行改进。但是提出问题,我会尽力回答。

祝你好运!

于 2012-11-16T19:51:52.513 回答