From bb94877353c2dd6b0b1cb2fe9facc9df47365484 Mon Sep 17 00:00:00 2001 From: Geremia Taglialatela Date: Wed, 3 Jun 2026 10:49:05 +0200 Subject: [PATCH] Skip validation when csvValidate is false Currently, the runtime only skips validation if the `data-csv-validate` attribute is missing. If it's explicitly set to `"false"`, the element is still included in the validation inputs because `"false" == null` is false. Change the check to ensure that only elements with `csvValidate` set to `"true"` are validated. This allows users to dynamically disable validation for specific elements by setting the attribute to `"false"`. --- CHANGELOG.md | 1 + dist/client-side-validations.esm.js | 2 +- dist/client-side-validations.js | 2 +- src/index.js | 2 +- .../public/test/form_builders/validateForm.js | 20 +++++++++++++++++++ .../assets/javascripts/rails.validations.js | 2 +- 6 files changed, 25 insertions(+), 4 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index cd062561..ac7367c3 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -6,6 +6,7 @@ - Deep imports of `src/validators/local/*` must use named exports instead of the removed default object exports, for example `import { acceptanceLocalValidator } from '@client-side-validations/client-side-validations/src/validators/local/acceptance'` - Remove the unused `addClass` and `removeClass` exports from `src/utils.js` - Explicitly remove dead \`inputs\` and \`validate_inputs\` entries from \`ClientSideValidations.selectors\`; only \`forms\` is read by the runtime` +* [BUGFIX] Correctly skip validation for elements where `data-csv-validate` is explicitly set to `"false"` ## 24.0.0 / 2026-04-19 * [FEATURE] Breaking change: Remove the jQuery runtime dependency and the old jQuery plugin aliases from the published JavaScript assets diff --git a/dist/client-side-validations.esm.js b/dist/client-side-validations.esm.js index d7719060..cc9759a2 100644 --- a/dist/client-side-validations.esm.js +++ b/dist/client-side-validations.esm.js @@ -673,7 +673,7 @@ const validatorsFor = (elementName, validators) => { }; const getValidationInputs = form => { return Array.from(form.elements).filter(element => { - if (element.dataset.csvValidate == null || element.disabled) { + if (element.dataset.csvValidate !== 'true' || element.disabled) { return false; } return isVisible(element); diff --git a/dist/client-side-validations.js b/dist/client-side-validations.js index 3efe78ae..30ca077c 100644 --- a/dist/client-side-validations.js +++ b/dist/client-side-validations.js @@ -679,7 +679,7 @@ }; const getValidationInputs = form => { return Array.from(form.elements).filter(element => { - if (element.dataset.csvValidate == null || element.disabled) { + if (element.dataset.csvValidate !== 'true' || element.disabled) { return false; } return isVisible(element); diff --git a/src/index.js b/src/index.js index e271cd10..3a180ef3 100644 --- a/src/index.js +++ b/src/index.js @@ -102,7 +102,7 @@ const validatorsFor = (elementName, validators) => { const getValidationInputs = (form) => { return Array.from(form.elements).filter((element) => { - if (element.dataset.csvValidate == null || element.disabled) { + if (element.dataset.csvValidate !== 'true' || element.disabled) { return false } diff --git a/test/javascript/public/test/form_builders/validateForm.js b/test/javascript/public/test/form_builders/validateForm.js index 3aeba636..2ce68f66 100644 --- a/test/javascript/public/test/form_builders/validateForm.js +++ b/test/javascript/public/test/form_builders/validateForm.js @@ -272,6 +272,26 @@ QUnit.test('Disable client side validations on all child inputs', function (asse assert.notOk(input.parentElement.querySelector('label.message')) }) +QUnit.test('Validate form with an input with csvValidate set to false (async)', function (assert) { + var done = assert.async() + var form = document.getElementById('new_user') + var input = document.getElementById('user_name') + + input.value = '' + input.dataset.csvValidate = 'false' + + form.requestSubmit() + + setTimeout(function () { + var iframe = document.querySelector('iframe') + var response = iframe && iframe.contentDocument && iframe.contentDocument.querySelector('#response') + + assert.notOk(input.parentElement.classList.contains('field_with_errors'), 'Input should not have errors because validation was skipped') + assert.ok(response, 'Form should have been submitted successfully') + done() + }, 250) +}) + QUnit.test('Disable ignores non-element nodes in mixed collections', function (assert) { var input = document.getElementById('user_name') var textNode = document.createTextNode('ignored node') diff --git a/vendor/assets/javascripts/rails.validations.js b/vendor/assets/javascripts/rails.validations.js index 3efe78ae..30ca077c 100644 --- a/vendor/assets/javascripts/rails.validations.js +++ b/vendor/assets/javascripts/rails.validations.js @@ -679,7 +679,7 @@ }; const getValidationInputs = form => { return Array.from(form.elements).filter(element => { - if (element.dataset.csvValidate == null || element.disabled) { + if (element.dataset.csvValidate !== 'true' || element.disabled) { return false; } return isVisible(element);