From 4e473dd2cbb591d7c7049f766b8a824eedc6b839 Mon Sep 17 00:00:00 2001 From: f Date: Wed, 19 Jun 2024 13:12:54 -0300 Subject: [PATCH 1/3] fix: validar con stimulus --- .../controllers/form_validation_controller.js | 29 ++++++++++++++++ app/javascript/etc/index.js | 1 - app/javascript/etc/validation.js | 34 ------------------- app/views/posts/_form.haml | 2 +- 4 files changed, 30 insertions(+), 36 deletions(-) create mode 100644 app/javascript/controllers/form_validation_controller.js delete mode 100644 app/javascript/etc/validation.js diff --git a/app/javascript/controllers/form_validation_controller.js b/app/javascript/controllers/form_validation_controller.js new file mode 100644 index 00000000..fe65934e --- /dev/null +++ b/app/javascript/controllers/form_validation_controller.js @@ -0,0 +1,29 @@ +import { Controller } from "stimulus"; + +export default class extends Controller { + connect() { + this.element.setAttribute("novalidate", true); + + for (const input of this.element.elements) { + if (input.type === "button" || input.type === "submit") continue; + + if (input.dataset.action) { + input.dataset.action = `${input.dataset.action} htmx:validation:validate->form-validation#submit`; + } else { + input.dataset.action = "htmx:validation:validate->form-validation#submit"; + } + } + } + + submit(event = undefined) { + event?.preventDefault(); + event?.stopPropagation(); + + if (this.element.reportValidity()) { + this.element.classList.remove("was-validated"); + this.element.submit(); + } else { + this.element.classList.add("was-validated"); + } + } +} diff --git a/app/javascript/etc/index.js b/app/javascript/etc/index.js index 3a1ef75c..641d8085 100644 --- a/app/javascript/etc/index.js +++ b/app/javascript/etc/index.js @@ -4,6 +4,5 @@ import './input-tag' import './prosemirror' import './timezone' import './turbolinks-anchors' -import './validation' import './new_editor' import './htmx_abort' diff --git a/app/javascript/etc/validation.js b/app/javascript/etc/validation.js deleted file mode 100644 index 5a48148f..00000000 --- a/app/javascript/etc/validation.js +++ /dev/null @@ -1,34 +0,0 @@ -document.addEventListener('turbolinks:load', () => { - // Al enviar el formulario del artículo, aplicar la validación - // localmente y actualizar los comentarios para lectores de pantalla. - document.querySelectorAll('form').forEach(form => { - form.addEventListener('submit', event => { - const invalid_help = form.querySelectorAll('.invalid-help') - const sending_help = form.querySelectorAll('.sending-help') - - invalid_help.forEach(i => i.classList.add('d-none')) - sending_help.forEach(i => i.classList.add('d-none')) - - form.querySelectorAll('[aria-invalid="true"]').forEach(aria => { - aria.setAttribute('aria-invalid', false) - aria.setAttribute('aria-describedby', aria.parentElement.querySelector('.feedback').id) - }) - - if (form.checkValidity() === false) { - event.preventDefault() - event.stopPropagation() - - invalid_help.forEach(i => i.classList.remove('d-none')) - - form.querySelectorAll(':invalid').forEach(invalid => { - invalid.setAttribute('aria-invalid', true) - invalid.setAttribute('aria-describedby', invalid.parentElement.querySelector('.invalid-feedback').id) - }) - } else { - sending_help.forEach(i => i.classList.remove('d-none')) - } - - form.classList.add('was-validated') - }) - }) -}) diff --git a/app/views/posts/_form.haml b/app/views/posts/_form.haml index 8a86d203..aa8f3d1d 100644 --- a/app/views/posts/_form.haml +++ b/app/views/posts/_form.haml @@ -33,7 +33,7 @@ - dir = t("locales.#{@locale}.dir") -# Comienza el formulario -= form_tag url, method: method, class: "form post #{extra_class}", multipart: true, data: { controller: 'unsaved-changes', action: 'unsaved-changes#submit beforeunload@window->unsaved-changes#unsaved turbolinks:before-visit@window->unsaved-changes#unsavedTurbolinks', 'unsaved-changes-confirm-value': t('.confirm') } do += form_tag url, method: method, class: "form post #{extra_class}", multipart: true, data: { controller: 'unsaved-changes form-validation', action: 'unsaved-changes#submit form-validation#submit beforeunload@window->unsaved-changes#unsaved turbolinks:before-visit@window->unsaved-changes#unsavedTurbolinks', 'unsaved-changes-confirm-value': t('.confirm') } do -# Botones de guardado = render 'posts/submit', site: site, post: post From 4cdfbb7b2f48ccef20eca1cc2a683ff8a4217709 Mon Sep 17 00:00:00 2001 From: f Date: Wed, 19 Jun 2024 13:13:09 -0300 Subject: [PATCH 2/3] =?UTF-8?q?fix:=20validaci=C3=B3n=20en=20modo=20oscuro?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- app/assets/stylesheets/application.scss | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/app/assets/stylesheets/application.scss b/app/assets/stylesheets/application.scss index 4b659972..ce0b0924 100644 --- a/app/assets/stylesheets/application.scss +++ b/app/assets/stylesheets/application.scss @@ -95,6 +95,16 @@ $sizes: ( box-shadow: 0 0 0 0.2rem $cyan; } } + + @include form-validation-state("valid", $cyan, url("data:image/svg+xml,")); + + .custom-checkbox { + .custom-control-input:checked ~ .custom-control-label { + &::after { + background-image: url("data:image/svg+xml,"); + } + } + } } // TODO: Encontrar la forma de generar esto desde los locales de Rails From 2ec752ee1406769eaddb03f9aa569ec4e6c0a84f Mon Sep 17 00:00:00 2001 From: f Date: Wed, 19 Jun 2024 13:13:30 -0300 Subject: [PATCH 3/3] =?UTF-8?q?feat:=20validaci=C3=B3n=20de=20new=5Farray?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../controllers/required_checkbox_controller.js | 15 +++++++++++++++ app/views/posts/attributes/_new_array.haml | 9 +++++---- config/locales/en.yml | 1 + config/locales/es.yml | 1 + 4 files changed, 22 insertions(+), 4 deletions(-) diff --git a/app/javascript/controllers/required_checkbox_controller.js b/app/javascript/controllers/required_checkbox_controller.js index 9754b506..a24ce881 100644 --- a/app/javascript/controllers/required_checkbox_controller.js +++ b/app/javascript/controllers/required_checkbox_controller.js @@ -20,5 +20,20 @@ export default class extends Controller { } else { this.requiredTarget.required = !Array.from(this.checkboxTargets).some(x => x.checked); } + + for (const checkbox of this.checkboxTargets) { + if (checkbox === event.target) continue; + + checkbox.required = !event.target.checked; + } + } + + /* + * Si el checkbox es considerado + */ + invalid(event) { + for (const checkbox of this.checkboxTargets) { + checkbox.required = true; + } } } diff --git a/app/views/posts/attributes/_new_array.haml b/app/views/posts/attributes/_new_array.haml index 4293ded1..5778f619 100644 --- a/app/views/posts/attributes/_new_array.haml +++ b/app/views/posts/attributes/_new_array.haml @@ -15,11 +15,12 @@ Si la lista es obligatoria, al menos uno de los ítems tiene que estar activado. Logramos esto con un checkbox oculto que se marca como obligatorio al validar el formulario. - - if metadata.required - %input.form-control{ type: 'checkbox', name: name, data: { target: 'required-checkbox.required' }, required: metadata.value.empty? } - .invalid-feedback Requerido! .d-flex.align-items-center.justify-content-between - = label_tag id, post_label_t(attribute, post: post) + %div + = label_tag id, post_label_t(attribute, post: post), class: 'mb-0' + - if metadata.required + %input.form-control.d-none{ type: 'checkbox', name: name, data: { target: 'required-checkbox.required', action: 'invalid->required-checkbox#invalid' }, required: metadata.value.empty? } + .invalid-feedback.mt-0= t('.required') = render 'bootstrap/btn', content: t('.edit'), action: 'modal#show' -# Mostramos la lista de valores actuales. diff --git a/config/locales/en.yml b/config/locales/en.yml index 94a6968a..6b8562d1 100644 --- a/config/locales/en.yml +++ b/config/locales/en.yml @@ -764,6 +764,7 @@ en: edit: "Edit" new_array: edit: "Edit" + required: "Please select at least one option." new_has_one: edit: "Edit" new_belongs_to: diff --git a/config/locales/es.yml b/config/locales/es.yml index fcaa6658..d1c61fd2 100644 --- a/config/locales/es.yml +++ b/config/locales/es.yml @@ -772,6 +772,7 @@ es: edit: "Editar" new_array: edit: "Editar" + required: "Seleccioná al menos una opción." new_has_one: edit: "Editar" new_belongs_to: