Вопрос по ajax, ruby-on-rails, jquery – Форма AJAX (с использованием simple_form) с сохраненной проверкой ошибок

19

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

Я работаю над фиктивным приложением, которое примерно следует этому руководству ... ajax / jquery tutorial ...

Делая мои собственные настройки, это руководство помогло мне создать форму представления «бренд» (включая вложенные модели «модель», «подмодель» и «стиль») (с использованием simple_form) и список брендов на одной странице. Это работает отлично, и проверка (для моих моделей) обязательна. Однако, когда я помещаю форму и список брендов на одной странице, я теряю аккуратные встроенные ошибки проверки, которые появлялись при сбое отправки (см. изображение ниже). Отсутствие возможности исправлять встроенные ошибки заставило меня осознать, что мне нужно больше узнать о рендеринге ... и поэтому я зациклен на поиске ответа на этот вопро

... а вот и список:

Below - контроллер для действия индекса:

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

Приведенная выше форма создает марку, модель, подмодель и стиль для использования во вложенной форме отправки ... Ниже приведен код формы:

<code><%= 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 %>
</code>

Теперь, как ты видишь, я использую:remote => true ... Я хотел бы, чтобы форма создала новый «бренд», или чтобы она перезагрузилась с внутренними ошибками проверки. На данный момент мое действие создания выглядит та

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

Код, который появляется подif @brand.saveажется, что @ работает .. но код ниже "else" не работает так, как мне бы хотелось Так что же происходит, когда @brand НЕ сохраняет? Я полагаю, что код в действии index выполняется, затем @ brand.errors преобразуется в json (что я предполагаю для ошибок проверки simple_form), а затем выполняется reload.js.erb ..

При попытке перезагрузить форму (с ошибками проверки) я поставил строку$("#entryform").load(location.href+" #entryform>*",""); into reload.js.erb ... Когда я помещаю недопустимые данные в мою форму, вызывается reload.js.erb, но все, что происходит, - это то, что поля формы перезагружаются пустыми, вместо ввода данных и встроенных ошибок проверки.

Надеюсь, что предоставил достаточно информации, чтобы получить помощь. Благодарность

Этота близко к тому, что я пытаюсь сделать, но у меня не получается. К сожалению, руководство, указанное в исходном вопросе, исчезло. При звонкеsimple_form_for, ты не поставил"data-type" => :json? В контроллере нужно ли звонить какformat.json а такж format.js? И в JavaScript вам не нужно возвращать@brand.errors как локальная переменная? Возможно это отличается, потому что я использую модальный. Я начал новый вопрос в надежде получить разъяснение: Отображение встроенных ошибок с помощью simple_form в модале Bootstrap Ajax Mark Berry

Ваш Ответ

3   ответа
30

что вы можете упростить это, поместив свою форму в частичную (мы назовем ееsimple_form) и поместим этот код в reload.js.erb:

$("#entryform").html("<%= escape_javascript(render :partial => 'simple_form') %>");

Я не знаком с jQuery'sload метод, но я предполагаю, что это делает второй запрос. Ключ с ошибками рендеринга - переменная экземпляра @brand) форма, которую вы используете при рендеринге, должна быть такой же, как вы пытались сохранить в create, чтобы вы могли проверить на ней ошибки. Вот почему вы всегда используетеrender вместо тогоredirect_to когда вы хотите сделать ошибки. Если вы делаете перенаправление, вы начинаете новый запрос, что означает@brand повторно инициализируется. Я предполагаю, что ваш$(...).load(...) @ та же проблема.

Не только вы ответили на мой вопрос (с простым рабочим решением) .. вы также предоставили отличное объяснение. Большой Abram
С этим методом может быть проблема, если у вас есть какой-либо прикрепленный javascript к любому из элементов внутри формы, он не будет работать после того, как форма будет отображена с ошибками NoDisplayName
@ JustMichael в этом случае присоединяет обработчики событий к родительским элементам, например вместо$('#target').on('click', function(e){ ... }) использовать$(document).on('click', '#target', function(e){ ... }) Konstantin Kalbazov
@ Котэ, если бы я знал это тогда NoDisplayName
1

Упрощение структуры файла @ tsherif на одну ступеньку (при условии, что у вас уже есть файл js), я решил эту проблему, вызвав render непосредственно в форме и показав его через 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)
0

вызов .html (...) будет дублировать div обертки формы. Вместо этого используйте .replateWith (...) =]

Похожие вопросы