Native Visibility Rules and Progressive Profiling pack immense power. But one thing they can’t do is change whether a field is required: if a field is displayed per VR and/or ProgPro rules, it simply picks up the Required setting from Form Editor.
This means you need JS for advanced behaviors. Say Country should be optional for Home users:

Country and Company are required for Professional and Enterprise. while Number of Employees is displayed (via native VRs) but optional for Professional:

And finally, Enterprise users must provide Country, Company and Number of Employees:

Enter manageFieldRequirement()
Here’s a little JS function that lets you achieve such special effects:
/**
* Programmatically require/unrequire a Marketo form field
* @author Sanford Whiteman
* @version v1.2 2025-08-25
* @license Hippocratic 3.0: This license must appear with all reproductions of this software.
*
*/
function manageFieldRequirement(mktoForm, fieldName, userOptions = {}){
const defaultOptions = {
require: false,
alsoFlipVisibility: false,
validationMessage: undefined
};
const options = Object.assign(defaultOptions, userOptions);
const formJq = mktoForm.getFormElem();
const fieldJq = formJq.find(`[name="${CSS.escape(fieldName)}"]`);
if(!fieldJq.length) {
return;
}
const rowJq = fieldJq.closest(".mktoFormRow");
const colJq = fieldJq.closest(".mktoFormCol");
const rowColCount = rowJq.find(".mktoFormCol").length;
const flippableJq = rowColCount === 1 ? rowJq : colJq;
const wrapperJq = fieldJq.closest(".mktoFieldWrap");
const descriptorJq = fieldJq.closest(".mktoFieldDescriptor");
if(options.require){
fieldJq.attr("aria-required","true");
fieldJq.addClass("mktoRequired");
wrapperJq.addClass("mktoRequiredField");
descriptorJq.data("mktoFieldDescriptor").required = true;
if(options.alsoFlipVisibility){
flippableJq.show();
}
} else {
fieldJq.removeAttr("aria-required");
fieldJq.removeClass("mktoRequired");
wrapperJq.removeClass("mktoRequiredField");
descriptorJq.data("mktoFieldDescriptor").required = false;
if(options.alsoFlipVisibility){
flippableJq.hide();
}
}
if(options.validationMessage){
descriptorJq.data("mktoFieldDescriptor").validationMessage = options.validationMessage;
}
}
(With platform features these days, you don’t need jQuery to manipulate the DOM. But here we specifically need jQuery data
, so decided to embrace the beast.)
Usage
manageFieldRequirement()
takes 3 params:
mktoForm
- a Marketo Forms 2.0 form object, e.g. the argument passed to awhenReady()
listenerfieldName
- the form field name, a.k.a. SOAP API nameuserOptions
- an object with a few properties:require
(Boolean, defaultfalse
) - require the field or un-require italsoFlipVisibility
(Boolean, defaultfalse
) - also show the field if required/hide if unrequiredvalidationMessage
(String, optional) - custom validation message to swap in
Example: Get the behavior shown in the screenshots above
Inside a Forms 2.0 whenReady()
listener, add a DOM change
listener. Then do advanced management of Country
and Company
fields:
MktoForms2.whenReady(function(readyForm){
const formEl = readyForm.getFormElem()[0];
formEl.addEventListener("change",function(e){
const currentValues = readyForm.getValues();
const requestedSubscriptionType = currentValues["SubscriptionType"];
if( !requestedSubscriptionType || requestedSubscriptionType === "Home" ) {
manageFieldRequirement(readyForm, "Country", { require: false });
manageFieldRequirement(readyForm, "Company", { require: false });
} else {
manageFieldRequirement(readyForm, "Country", { require: true, validationMessage: "Please provide Country for Pro and Enterprise accounts." });
manageFieldRequirement(readyForm, "Company", { require: true, validationMessage: "Company is required for Pro and Enterprise accounts." });
}
if( !requestedSubscriptionType || requestedSubscriptionType === "Home" || requestedSubscriptionType === "Professional" ) {
manageFieldRequirement(readyForm, "NumberOfEmployees", { require: false });
} else {
manageFieldRequirement(readyForm, "NumberOfEmployees", { require: true, validationMessage: "Number of employees is required for Enterprise accounts." });
}
});
// initialize state
formEl.dispatchEvent(new Event("change"));
});
N.B. The change
listener works even when Visibility Rules are also managing the field because new HTML element(s) are injected synchronously by the VR code, before the event bubbles up to the <form>
. This is good!