Визуализация ошибок валидации в приложении Rails 6 (с использованием simple_form & Bootstrap) при выполнении вызова AJAX - PullRequest
0 голосов
/ 19 марта 2020

Отказ от ответственности: Относительно плохо знаком с Ruby и Rails, так что я буду очень признателен за подробные ответы, чтобы я мог понять. :)

Я создаю приложение Rails (6.0.2) (с веб-пакетом), использую simple_form (5.0.2) для создания формы для отправки и Bootstrap (4.4.1) ) для стилизации UX.

Теперь я пытаюсь создать одностраничное приложение Rails и добавил кнопки Next / Previous с AJAX вызовами, выполняемыми с использованием jQuery, и пока все хорошо. У меня также есть кнопка Submit , которая запускает множество проверок на входах и возвращает ошибки, если таковые обнаружены. При использовании обычной кнопки Submit f.submit (предоставляемой simple_form) URL-адрес изменяется на URL-адрес PUT / PATCH, в то время как страница перерисовывается, а ошибки отображаются на экране (как и ожидалось).

Пользовательский поток таков, что новый пациент генерируется автоматически (в JS), так что они перенаправляются на URL-адрес редактирования, в то время как существующий пациент будет перенаправлен на URL-адрес редактирования независимо от этого. Начиная с URL-адреса редактирования, они будут вносить изменения в поля формы, пока не будут готовы к отправке. Это где у меня проблемы, однако.

Желая получить одностраничное приложение, я решил сделать свою собственную кнопку отправки (которая отправляет запрос AJAX PATCH), что также заканчивается запуск проверки. Сетевая активность (в Chrome Dev Tools) фактически показывает ответ, возвращаемый с визуализацией встроенных проверок, однако я перенаправлен обратно на страницу редактирования, таким образом стирая эти ошибки. Logi c, который обеспечивает выполнение проверок проверки, здесь не используется, но я убедился, что не проблема.

Существует ли простой способ использовать существующую ошибку проверки Интеграции, которые существуют между simple_form и Bootstrap в вызове AJAX?

Представление simple_form:

-# frozen_string_literal: true
= simple_form_for(@patient_intake_form) do |f|
  = f.error_notification
  = f.error_notification message: f.object.errors[:base].to_sentence if f.object.errors[:base].present?

(...)

  .form-actions    
    .form_prev
      = link_to 'Previous', '#', class: 'prev_section change_section btn btn-outline-prev'
    .form_next
      = link_to 'Next', '#', class: 'next_section change_section btn btn-next'
    .form_submit
      = link_to 'Submit', '#', class: 'submit_form change_section btn btn-submit'

javascript, выполняемое на кнопках Next / Previous и Submit:

$(document).on('turbolinks:load', () => {
  if ($('body.patient_intakes-new').length) {
    $.post({url: "/patient_intakes/", data: $('.simple_form').serialize()});
  };

  $('.change_section').on('click', () => {
    section_data = $('.simple_form').find('.active :input').serialize();
    if (section_data.length) {
      request = $.ajax({
        type: "PATCH",
        url: '.',
        data: section_data
      });
    }
   });
});

И контроллер:

class PatientIntakesController < ApplicationController
  load_and_authorize_resource :patient_intake_form
  before_action :prepare_intake_form, only: [:edit, :update]

  # GET /patient_intakes/new
  def new
    intake_form = IntakeForm.find_by(user_id: current_user.id)
    if intake_form
      redirect_to edit_patient_intake_path(intake_form.id)
      return
    end
    @patient_intake_form = PatientIntakeForm.new
    @patient_intake_form.prepopulate!(email: current_user.email)
  end

  # GET /patient_intakes/1/edit
  def edit
  end

  # POST /patient_intakes
  # POST /patient_intakes.json
  def create
    @patient_intake_form = PatientIntakeForm.new

    respond_to do |format|
      if @patient_intake_form.validate(patient_params)
        @patient_intake_form.save
        if @patient_intake_form.status == 'in_review'
          format.html { redirect_to '/submission' }
        else
          format.html { redirect_to edit_patient_intake_path(@patient_intake_form.to_param) }
        end
      else
        format.html { render :new }
        format.json { render json: @patient_intake_form.errors, status: :unprocessable_entity }
      end
    end
  end

  # PATCH/PUT /patient_intakes/1
  # PATCH/PUT /patient_intakes/1.json
  def update
    respond_to do |format|
      if @patient_intake_form.validate(patient_params)
        @patient_intake_form.save
        if @patient_intake_form.status == 'in_review'
          format.html { redirect_to '/submission' }
        else
          format.html { render :edit }
          format.json { render json: @patient_intake_form }
        end
      else
        format.html { render :edit }
        format.json { render json: @patient_intake_form.errors, status: :unprocessable_entity }
      end
    end
  end

  private
    # Use callbacks to share common setup or constraints between actions.
    def prepare_intake_form
      @patient_intake_form = PatientIntakeForm.find(params[:id])
    end

    # Never trust parameters from the scary internet, only allow the white list through.
    def patient_params
      params.require(:patient_intake).merge(user_id: current_user.id)
    end
end

Я обнаружил, что также могу заставить кнопку f.submit Submit запускать AJAX POST-вызовы, установив remote: true к инициализации формы и добавлению format.js {} к форматам создания / обновления, что позволяет мне сделать приложение полностью одностраничным. Другие вопросы StackOverflow решали эту проблему в некотором роде, но я не смог заставить эти решения работать, такие как:

AJAX форма (с использованием simple_form) с сохраненной проверкой ошибок

Любые указатели, советы будут наиболее ценными !! Ура! :)

...