我一辈子都无法让 RJS 用实例变量的属性替换元素的 innerHTML,即类似@thing.name
我将展示所有代码(从实际项目中简化,但仍然完整),我希望解决方案对某人来说是显而易见的......
在 RoR 中,我制作了一个显示随机汉字的简单页面。
这是一个Word
具有属性chinese
和的对象english
。
点击标题为“这是什么?”的链接 使用 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
顺便说一句,SQL 调用:limit => 100
只是为了以防我想出某种方法来循环遍历这些随机单词。目前它没有用。此外,据我所知,“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。
“字符”部分看起来像这样(它是 erb,没有真正的原因):
<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
,并将其指向一个用新的东西替换“字符”元素的 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}")
我收到一个错误,说我给它一个 nil 对象:
ActionView::TemplateError (undefined method `english_name' for nil:NilClass) on line #1 of app/views/words/second_character.rjs: 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
最明显的是在选项中 - 并研究参数中传递的内容,但无济于事。在这一点上,我意识到我不知道自己在做什么。
这是我在这里的第一个问题。我错误地提供了所有必要的代码,而不是简短。任何帮助将不胜感激。