I have a Marketo form for an event where I want to enable the submit button only after the user has entered the correct value in the event code field? How do I do this? I have the Global Validation Rule enabled already to check for email ID entered. This particular check is for a different field.
Solved! Go to Solution.
OK. First, you don’t want to disable the button because that breaks even the ability to validate the form. (This is a restriction enforced by the HTML engine.)
But you can make the button appear disabled by greying it out if a field is (HTML-)invalid. Then add some JS to perform the Marketo validation as well.
A combination of the following CSS + JS will get you what you want.
The CSS:
.mktoForm:has([data-extended-invalid="true"]) .mktoButton {
opacity: .5;
cursor: not-allowed;
}
The JS:
{
const requiredPatterns = [
{
field: "EventCode",
pattern: "ABC",
message: "You must provide the correct event code."
}
];
/* -- NO NEED TO MODIFY BELOW HERE -- */
MktoForms2.whenReady(function(readyForm){
const formEl = readyForm.getFormElem()[0];
// platform validation to enable instant CSS restyling
// also append the element
for( let [idx,desc] of requiredPatterns.entries() ) {
desc.regexp = desc.pattern instanceof RegExp ? desc.pattern : new RegExp("^" + desc.pattern + "$");
desc.el = formEl.querySelector(`[name='${CSS.escape(desc.field)}']`)
if( desc.el ) {
// on platform event
desc.el.addEventListener("input", () => extendedValidate(true) );
} else {
delete requiredPatterns[idx]; // yeah, sparsify, sue me
}
}
requiredPatterns.sort( ({el: elA}, {el: elB}) => {
const pos = elA.compareDocumentPosition(elB);
if( pos & Node.DOCUMENT_POSITION_FOLLOWING ) {
return -1;
} else if( pos & Node.DOCUMENT_POSITION_PRECEDING ) {
return 1;
} else {
return 0;
}
});
// on Marketo event
readyForm.onValidate(function(nativeValid){
if( nativeValid ) extendedValidate(false);
});
// on initial ready
extendedValidate(true);
function extendedValidate(silent){
let originalSubmittable = readyForm.submittable();
readyForm.submittable(false);
const currentValues = readyForm.getValues();
let firstError;
for( let desc of requiredPatterns ) {
if( desc ) {
if( !desc.regexp.test(currentValues[desc.field]) ){
firstError = desc;
desc.el.dataset.extendedInvalid = true;
} else {
delete desc.el.dataset.extendedInvalid;
}
}
}
if( firstError && !silent ) {
setTimeout( () => readyForm.showErrorMessage(firstError.message, MktoForms2.$(firstError.el)), 140 );
}
readyForm.submittable(originalSubmittable);
}
});
}
That’ll give you output like this on submit:
How do you define the "correct" value in this case? Is it the same exact value for everyone filling out this form?
Yes @SanfordWhiteman , it is one specific value for everyone filling the form.
OK. First, you don’t want to disable the button because that breaks even the ability to validate the form. (This is a restriction enforced by the HTML engine.)
But you can make the button appear disabled by greying it out if a field is (HTML-)invalid. Then add some JS to perform the Marketo validation as well.
A combination of the following CSS + JS will get you what you want.
The CSS:
.mktoForm:has([data-extended-invalid="true"]) .mktoButton {
opacity: .5;
cursor: not-allowed;
}
The JS:
{
const requiredPatterns = [
{
field: "EventCode",
pattern: "ABC",
message: "You must provide the correct event code."
}
];
/* -- NO NEED TO MODIFY BELOW HERE -- */
MktoForms2.whenReady(function(readyForm){
const formEl = readyForm.getFormElem()[0];
// platform validation to enable instant CSS restyling
// also append the element
for( let [idx,desc] of requiredPatterns.entries() ) {
desc.regexp = desc.pattern instanceof RegExp ? desc.pattern : new RegExp("^" + desc.pattern + "$");
desc.el = formEl.querySelector(`[name='${CSS.escape(desc.field)}']`)
if( desc.el ) {
// on platform event
desc.el.addEventListener("input", () => extendedValidate(true) );
} else {
delete requiredPatterns[idx]; // yeah, sparsify, sue me
}
}
requiredPatterns.sort( ({el: elA}, {el: elB}) => {
const pos = elA.compareDocumentPosition(elB);
if( pos & Node.DOCUMENT_POSITION_FOLLOWING ) {
return -1;
} else if( pos & Node.DOCUMENT_POSITION_PRECEDING ) {
return 1;
} else {
return 0;
}
});
// on Marketo event
readyForm.onValidate(function(nativeValid){
if( nativeValid ) extendedValidate(false);
});
// on initial ready
extendedValidate(true);
function extendedValidate(silent){
let originalSubmittable = readyForm.submittable();
readyForm.submittable(false);
const currentValues = readyForm.getValues();
let firstError;
for( let desc of requiredPatterns ) {
if( desc ) {
if( !desc.regexp.test(currentValues[desc.field]) ){
firstError = desc;
desc.el.dataset.extendedInvalid = true;
} else {
delete desc.el.dataset.extendedInvalid;
}
}
}
if( firstError && !silent ) {
setTimeout( () => readyForm.showErrorMessage(firstError.message, MktoForms2.$(firstError.el)), 140 );
}
readyForm.submittable(originalSubmittable);
}
});
}
That’ll give you output like this on submit: