Отказ от ответственности: Относительно плохо знаком с 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) с сохраненной проверкой ошибок
Любые указатели, советы будут наиболее ценными !! Ура! :)