skip validation when novalidate or form submitted indirectly

This commit is contained in:
Matthew Molloy 2020-12-27 12:59:48 +07:00
parent 5fd24a7096
commit e01c7f77e4
2 changed files with 40 additions and 6 deletions

View File

@ -1506,7 +1506,7 @@ return (function () {
return true; return true;
} }
function processInputValue(processed, values, errors, elt) { function processInputValue(processed, values, errors, elt, validate) {
if (elt == null || haveSeenNode(processed, elt)) { if (elt == null || haveSeenNode(processed, elt)) {
return; return;
} else { } else {
@ -1544,12 +1544,14 @@ return (function () {
values[name] = value; values[name] = value;
} }
} }
validateElement(elt, errors); if (validate) {
validateElement(elt, errors);
}
} }
if (matches(elt, 'form')) { if (matches(elt, 'form')) {
var inputs = elt.elements; var inputs = elt.elements;
forEach(inputs, function(input) { forEach(inputs, function(input) {
processInputValue(processed, values, errors, input); processInputValue(processed, values, errors, input, validate);
}); });
} }
} }
@ -1569,20 +1571,23 @@ return (function () {
var values = {}; var values = {};
var errors = []; var errors = [];
// only validate when form is directly submitted and novalidate is not set
var validate = matches(elt, 'form') && elt.noValidate !== true;
// for a non-GET include the closest form // for a non-GET include the closest form
if (verb !== 'get') { if (verb !== 'get') {
processInputValue(processed, values, errors, closest(elt, 'form')); processInputValue(processed, values, errors, closest(elt, 'form'), validate);
} }
// include the element itself // include the element itself
processInputValue(processed, values, errors, elt); processInputValue(processed, values, errors, elt, validate);
// include any explicit includes // include any explicit includes
var includes = getClosestAttributeValue(elt, "hx-include"); var includes = getClosestAttributeValue(elt, "hx-include");
if (includes) { if (includes) {
var nodes = getDocument().querySelectorAll(includes); var nodes = getDocument().querySelectorAll(includes);
forEach(nodes, function(node) { forEach(nodes, function(node) {
processInputValue(processed, values, errors, node); processInputValue(processed, values, errors, node, validate);
}); });
} }

View File

@ -26,6 +26,35 @@ describe("Core htmx client side validation tests", function(){
form.textContent.should.equal("Clicked!"); form.textContent.should.equal("Clicked!");
}); });
it('Novalidate skips form validation', function()
{
this.server.respondWith("POST", "/test", "Clicked!");
var form = make('<form hx-post="/test" hx-trigger="click" novalidate>' +
'No Request' +
'<input id="i1" name="i1" required>' +
'</form>');
form.textContent.should.equal("No Request");
form.click();
this.server.respond();
form.textContent.should.equal("Clicked!");
});
it('Validation skipped for indirect form submission', function()
{
this.server.respondWith("POST", "/test", "Clicked!");
var form = make('<form hx-post="/test" hx-trigger="click">' +
'No Request' +
'<input id="i1" name="i1" required>' +
'<button id="button" hx-post="/test" hx-target="form"></button>' +
'</form>');
form.textContent.should.equal("No Request");
byId("button").click();
this.server.respond();
form.textContent.should.equal("Clicked!");
});
it('HTML5 pattern validation error prevents request', function() it('HTML5 pattern validation error prevents request', function()
{ {
this.server.respondWith("POST", "/test", "Clicked!"); this.server.respondWith("POST", "/test", "Clicked!");