Используйте JS для изменения <form>с удаленного на не удаленный в Rails 3, HAML - PullRequest
15 голосов
/ 28 марта 2012

Проблема в том, что у меня есть удаленная форма, которую, в зависимости от условия, я хотел бы преобразовать в не удаленную форму (используя UJS), а затем отправить. обратите внимание, что в форму загружен файл.

Вот подробности: я изначально визуализировал удаленную форму, используя

= form_for @myobj, :url => {:action=>"remoteAction", :controller=>"myobjects"}, :remote => true do |f|
... (f.fields....)

, который производит HTML:

<form id="new_myobj" class="new_myobj" method="post" accept-charset="UTF-8" data-remote="true" action="/remoteAction">

когда я нажимаю «отправить», как и ожидалось, форма отправляется «AS JS». в действии контроллера я делаю некоторую проверку полей внутри отправленной формы. Если все проверки пройдены, я выполняю следующий шаблон .js.haml:

$('form#new_myobj').removeAttr("data-remote");
$('form#new_myobj').attr('enctype', 'multipart/form-data');
$('form#new_myobj').attr('action', '/myobjects/regularAction');

, который успешно изменяет HTML на странице (засвидетельствовано через Firebug) на:

<form id="new_myobj" class="new_myobj" method="post" accept-charset="UTF-8" enctype="multipart/form-data" action="/myobjects/regularAction">

так как форма содержит поле f.file_field, я должен отправить его как составную часть, чтобы изображение могло быть загружено, и я не могу отправить 'AS JS' Теперь, когда я нажимаю «Отправить», действие контроллера «обычное действие» действительно вызывается, но оно все еще «КАК JS»

вопрос в том, что еще мне нужно изменить в HTML, чтобы форму можно было отправлять не в формате xhr? это связано с заголовками?

Ответы [ 2 ]

38 голосов
/ 20 сентября 2012

jQuery немного сложно с атрибутами данных, так как оба читает теги данных HTML5, а также свое собственное хранилище, привязанное к Элемент DOM, который также называется данными. При записи в атрибут это значение копируется в собственное хранилище данных jQuerys (предположительно когда data("remote") вызывается).

Однако, это происходит только если данные jQuery пустые для этого имени. Таким образом, установка атрибута будет работать только один раз , после чего используется «кэшированное» значение даже если атрибут меняется. Для того, чтобы действительно избавиться от значение, нам нужно удалить атрибут и собственное хранилище jQuerys метод в таком порядке . Причина в том, что существует высокий уровень (element.removeData(…)) и функция низкого уровня (jQuery. removeData(element, …)). Бывший перечитывает данные HTML5 атрибут и сохраняет его в собственном хранилище jQuery. Используя скорее необычная функция низкого уровня, очевидно, работает также.

Кроме того, нам действительно нужно удалить атрибут - установив его в false не достаточно, так как Rails проверяет только form.data('remote') не является неопределенным (ищите его в jquery_ujs.js).

TL; DR:

  • attr("data-remote") != data("remote")
  • Эти две строки делают форму не удаленной (опять же). Заказ имеет значение.
  $("form").removeAttr("data-remote");
  $("form").removeData("remote");

Это задокументировано, если вы действительно знаете, что ищете:

StackOverflow не позволяет мне публиковать более двух ссылок, но вы можете угадать одну ссылку removeData. Функции высокого уровня связаны с функциями низкого уровня.

Предотвращение ошибки аутентификации токена в Rails 4 + : Как прокомментировал Стэн ниже, простое выполнение вышеизложенного приведет к ошибке InvalidAuthenticityToken. Обходной путь прост, хотя, смотрите здесь для деталей: https://stackoverflow.com/a/19858504/1684530

4 голосов
/ 28 марта 2012

Проблема в том, что ваш подход к отключению передачи Ajax не совсем корректен. Вам необходимо отменить привязку событий JavaScript, которые уже были добавлены rails.js (адаптер Rails UJS) к форме. Вы можете сделать это: $('form#new_myobj').unbind() чтобы отменить привязку всех событий, прикрепленных к форме. Вам также необходимо $('form#new_myobj').removeAttr('data-remote') и $('form#new_myobj').removeAttr('data-type') удалить атрибуты data-remote и data-type (если они есть).

...