Форма AJAX (с использованием simple_form) с сохраненной проверкой ошибок
Это может быть один из самых сложных вопросов, которые я задал, но я застрял в течение нескольких дней, и я подумал, что лучше всего получить поддержку от более опытного сообщества рельсов.
Я работаю над фиктивным приложением, которое следует за этим руководством примерно... ajax/jquery tutorial...
Создав собственные настройки, руководство помогло мне создать "бренд" (включает в себя вложенные модели "модель", "подмодель" и "стиль" ) форму представления (используя simple_form) и список брендов на той же странице. Это работает отлично, и валидация (для моих моделей) применяется. Однако, когда я помещаю форму и список брендов на той же странице, я теряю аккуратные встроенные ошибки проверки, которые появляются при сбое отправки (см. Изображение ниже). Невозможность получить встроенные ошибки для работы заставила меня понять, что мне нужно больше узнать об рендеринге.. и вот почему я зациклен на поиске ответа на этот вопрос
![enter image description here]()
... и вот список:
![enter image description here]()
Ниже приведен контроллер для действия индекса:
def index
#This is for the product listing
@brands = Brand.all.reverse
#This is for the form
@brand = Brand.new
@model = Model.new
@submodel = Submodel.new
@style = Style.new
respond_to do |format|
format.html
end
end
В приведенной выше форме создается марка, модель, подмодель и стиль для использования в вложенной форме отправки... Ниже приведен код формы:
<%= simple_form_for @brand, :html => { :class => 'form-horizontal' }, :remote => true do |m| %>
<fieldset style = "margin-top:34px;">
<legend></legend>
<%= m.input :name, :label => 'Brand' %>
<%= m.simple_fields_for :models, @model do |p| %>
<%= p.input :name, :label => 'Model' %>
<%= p.simple_fields_for :submodels, @submodel do |s| %>
<%= s.input :name, :label => 'Submodel' %>
<%= s.simple_fields_for :styles, @style do |ss| %>
<%= ss.input :name, :label => 'Style' %>
<% end %>
<% end %>
<% end %>
<div class="form-actions">
<%= m.submit nil, :class => 'btn btn-primary' %>
<%= link_to 'Cancel', brands_path, :class => 'btn' %>
</div>
</fieldset>
<% end %>
Теперь, когда вы видите, что я использую :remote => true
... Я бы хотел, чтобы форма создавала новый "бренд" или для того, чтобы форма перезагружалась встроенными ошибками проверки. На данный момент мое действие создается так:
def create
@brand = Brand.new(params[:brand])
respond_to do |format|
if @brand.save
format.html { redirect_to brands_url, notice: 'Brand was successfully created.' }
format.json { render json: @brand, status: :created, location: @brand }
format.js
else
format.html { render action: "index" }
format.json { render json: @brand.errors, status: :unprocessable_entity }
format.js { render 'reload' }
end
end
end
Код, который появляется под if @brand.save
, кажется, работает. но код ниже "else" не работает так, как хотелось бы. Итак, что происходит, когда @brand НЕ сохраняет? Я считаю, что код внутри действия индекса запускается, а затем @brand.errors преобразуется в json (который я предполагаю для ошибок проверки Simple_form), а затем выполняется перезагрузка .js.erb..
В попытке перезагрузить форму (с ошибками проверки) я поместил строку $("#entryform").load(location.href+" #entryform>*","");
в reload.js.erb... Когда я помещаю неверные данные в свою форму, вызывается reload.js.erb, но все, что происходит, состоит в том, что поля формы перезагружаются пустым, вместо того, чтобы вводить данные и встроенные ошибки проверки.
Надеюсь, что я предоставил достаточно информации здесь, чтобы получить помощь. На самом деле это борьба. Спасибо!
Ответы
Ответ 1
Я думаю, вы можете упростить это, поставив свою форму в частичном (назовем ее simple_form
) и поместив этот код в reload.js.erb:
$("#entryform").html("<%= escape_javascript(render :partial => 'simple_form') %>");
Я не знаком с методом jQuery load
, но я предполагаю, что он выполняет второй запрос. Ключ с ошибками рендеринга - это переменная экземпляра (@brand
), которую вы используете, в то время как рендеринг формы должен быть тем же, который вы пытались сохранить в создании, поэтому вы можете проверить на нем ошибки. Вот почему вы всегда используете render
вместо redirect_to
, когда хотите визуализировать ошибки. Если вы выполните перенаправление, вы начнете новый запрос, то есть @brand
будет повторно инициализирован. Я предполагаю, что ваш $(...).load(...)
имеет ту же проблему.
Ответ 2
Спасибо за все Q & A на этом. Это спасло меня.
Упрощение структуры файлов @tsherif на одну метку (если у вас уже есть файл js), я решил эту проблему, вызвав визуализацию непосредственно в форме и показывая ее через javascript/coffeescript.
#immediate_controller
def action_with_modal
@brand = params[:failed_brand] || Brand.new
end
#brands_controller
def create
@brand = Brand.new(params[:brand])
respond_to do |format|
if @brand.save
...
else
params[:failed_brand] = @brand
...
format.js { render 'simple_form' }
end
end
end
#coffeescript
$('form-selectors-here').on 'ajax:error', @reRegister
reRegister: (e, data) =>
$("div-that-contains-form").html(data.responseText)
Ответ 3
Проверьте это: вызов .html(...) будет дублировать оболочку формы div.
Используйте .replateWith(...) вместо =]