使用RJS将innerHTML替换为真实的实例变量

时间:2010-05-25 13:02:21

标签: ruby-on-rails partial rjs instance-variables

我不能为我的生活让RJS用实例变量的属性替换元素的innerHTML,即类似@thing.name

我会显示所有代码(从实际项目中简化,但仍然完整),我希望解决方案对于某人来说是显而易见的...

在RoR中,我制作了一个显示随机汉字的简单页面。

这是一个Word个对象,其属性为chineseenglish

点击标题为“这是什么?”的链接使用RJS显示english属性。目前,它还隐藏了“这是什么?”链接并显示“尝试另一个?”只重新加载页面的链接,有效地重新开始使用新的随机字符。

这很好,但页面上还有其他元素可以进行自己的数据库查询,因此我想通过AJAX调用加载一个新的随机字符,只留下页面的其余部分。

事实证明这比我预期的要困难:我使用link_remote_to和page.replace_html替换html没有问题,但我无法显示包含实例变量的任何内容。

我有一个Word资源和一个Page资源,它有一个主页,所有这些都是有趣的。在PagesController中,我做了几种方法来获取随机单词。任何一个都可以正常工作......

以下是代码:

class PagesController < ApplicationController
  def home

    all_words = Word.find(:all)
    @random_word = all_words.rand

    @random_words = Word.find(:all, :limit => 100, :order => 'rand()')
    @random_first = @random_words[1]

  end
end

顺便说一下,使用:limit => 100进行SQL调用以防万一我想到了一些循环遍历这些随机单词的方法。现在它没用。另外,据我所知,'rand()'是MySQL特有的。

在主页视图(它是HAML)中,我有:

#character_box
 = render(:partial => "character", :object => @random_word) if @random_word

#whatisthis
  = link_to_remote "☝ what is this?", :url => { :controller => 'words', :action => 'reveal_character' }, :html => { :title => "Click for the translation." }

#tryanother.{:style => "display:none"}
  = link_to "try another?", root_path

请注意,在这种情况下,#表示div(使用给定的ID),而不是注释,因为这是HAML。

“character”部分看起来像这样(这是错误的,没有实际原因):

<div id="character">
  <%= "#{@random_word.chinese}" } %>
</div>

<div id="revealed" style="display:none">
  <ul>
    <li><span id="english"><%= "#{@random_word.english_name}" %></span></li>
  </ul>
</div>

reveal_character.rjs文件如下所示:

page[:revealed].visual_effect :slide_down, :duration => '.2'
page[:english].visual_effect :highlight,
                             :startcolor => "#ffff00",
                             :endcolor => "#ffffff",
                             :duration => '2.5'

page.delay(0.8) do
  page[:whatisthis].visual_effect :fade, :duration => '.3'
  page[:tryanother].visual_effect :appear
end

一切都很好。

但是,如果我尝试将link_to "try another?"转换为link_to_remote,并将其指向一个用新内容替换“character”元素的RJS模板,那么只有当我用静态文本替换innerHTML时它才有效。如果我尝试在那里传递一个实例变量,它永远不会起作用。

例如,假设我已经在Pages#home ...

下定义了第二个随机单词

我会在那里添加@random_second = @random_words[2]

然后,在主页视图中,我将替换“尝试另一个?”链接(以前指向root_path),其中包含:

= link_to_remote "try another?", :url => { :controller => 'words', :action => 'second_character' }, :html => { :title => "Click for a new character." }

我将在app / views / words / second_character.rjs上制作新的RJS模板,这样的简单测试表明它正在运行:

page.replace_html("character", "hi")

但如果我改成它:

page.replace_html("character", "#{@random_second.english}")

我得到一个错误,说我给它喂了一个零对象:

  

app / views / words / second_character.rjs第1行的ActionView :: TemplateError(未定义方法`english_name'代表nil:NilClass):   1:page.replace_html(“character”,“#{@ random_second.english}”)

当然,实际上实例化@random_second,@ random_third等无限广告在真正的应用程序中会很荒谬(我最终会想出一些更好的方法来继续抓取新的随机记录而不重新加载页面),但重点是我不知道如何让任何实例变量在这里工作。

这甚至不接近我渲染包含我指定的对象的部分的理想解决方案,如下所示:

page.replace_html 'character', :partial => 'new_character', :object => @random_second

由于我无法直接使用实例变量,我显然无法通过部分工作来实现它。

我尝试了各种各样的事情:

:object => @random_second

:locals => { :random_second => @random_second }

我尝试将这些添加到所有地方 - 最明显的是link_to_remote选项 - 并研究参数中传递的内容,但无济于事。就在这时,我意识到我不知道自己在做什么。

这是我的第一个问题。我错误地提供了所有必要的代码,而不是简短的。任何帮助将不胜感激。

2 个答案:

答案 0 :(得分:0)

方法replace_html将哈希作为其第二个参数。我想你需要说一些:

page.replace_html "character", :text => "#{@random_second.english}"

答案 1 :(得分:0)

你似乎搞混了。

要么使用link_to_function,它不会再次进入控制器,并且可以使用初始控制器设置的实例变量(只需执行rjs或javascript操作页面)。

要么使用link_to_remote,要么必须在您的案例second_character中定义相应的控制器操作,并且必须设置对象@random_second。然后每次调用(单击)时,它都可以设置一个新值。

我希望这会有所帮助。