Использование RJS для замены innerHTML реальной переменной экземпляра - PullRequest
0 голосов
/ 25 мая 2010

Я не могу на всю жизнь заставить RJS заменить innerHTML элемента на атрибут переменной экземпляра, то есть что-то вроде @thing.name

Я покажу весь код (упрощенный от фактического проекта, но все еще завершенный), и я надеюсь, что решение кому-то станет очевидным ...

В RoR я сделал простую страницу со случайным китайским символом.

Это Word объект с атрибутами chinese и english.

Нажав на ссылку под названием "Что это?" показывает атрибут english, используя RJS. В настоящее время также скрывается «Что это?» ссылка и показывает "Попробуйте другой?" ссылка, которая просто перезагружает страницу, фактически начиная с нового случайного символа.

Это нормально, но на странице есть другие элементы, которые выполняют свои собственные запросы к базе данных, поэтому я хотел бы загрузить новый случайный символ с помощью вызова AJAX, оставив остальную часть страницы в покое.

Это оказалось сложнее, чем я ожидал: у меня нет проблем с заменой HTML-кода с использованием link_remote_to и page.replace_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 (с заданными идентификаторами), а не комментарии, потому что это HAML.

Частично "персонаж" выглядит следующим образом (это эрб, без реальной причины):

<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>

Файл reve_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, который заменяет элемент «character» чем-то новым, он работает только тогда, когда я заменяю 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." }

Я создам этот новый шаблон RJS в app / views / words / second_character.rjs, и простой тест, подобный этому, показывает, что он работает:

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

Но если я изменю это на:

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

Я получаю сообщение об ошибке, сообщив, что я выдал ему нулевой объект:

ActionView :: TemplateError (неопределенный метод `english_name 'для nil: NilClass) в строке # 1 файла app / views / words / second_character.rjs: 1: page.replace_html ("символ", "# {@ 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 голосов
/ 26 мая 2010

Вы, кажется, все перепутали.

Либо вы используете link_to_function, который больше не переходит к контроллеру и может использовать переменные экземпляра, установленные вашим первоначальным контроллером (и просто выполнить rjs или javascript для манипулирования страницей).

Либо вы используете link_to_remote, но затем вам нужно определить соответствующее действие контроллера, в вашем случае second_character, и это должно установить объект @random_second. И затем каждый раз, когда он вызывается (щелкается), он может устанавливать новое значение.

Надеюсь, это поможет.

0 голосов
/ 26 мая 2010

Метод replace_html принимает хеш в качестве второго параметра. Я думаю, вам нужно сказать что-то вроде:

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