1. Why This Matters
If the same user is selected for multiple approval roles, approvals lose segregation and audits become weak.
This validator blocks duplicate user selections at form submission time.
2. Where to Use in Joget
- Form Builder: add this as a Custom Validator on each approver-related field.
- Suitable fields: dropdown, select box, or user picker fields storing usernames.
- Not for Workflow Builder or API Builder: this is pre-submission form validation.
3. Configuration You Must Set
Update these field IDs to match your form:
reviewerauthorizerapprover
Attach the same validator script to each of these fields so each selected value is checked against the other roles.
4. Production-Ready Validator Code
import org.joget.apps.form.model.Element;
import org.joget.apps.form.model.Form;
import org.joget.apps.form.model.FormData;
import org.joget.apps.form.service.FormUtil;
import java.util.Arrays;
public boolean validate(Element element, FormData formData, String[] values) {
try {
String reviewerFieldName = "reviewer";
String authorizerFieldName = "Authorizer";
String approverFieldName = "Approver";
Form form = FormUtil.findRootForm(element);
Element reviewerElement = FormUtil.findElement(reviewerFieldName, form, formData);
Element authorizerElement = FormUtil.findElement(authorizerFieldName, form, formData);
Element approverElement = FormUtil.findElement(approverFieldName, form, formData);
if (values != null && reviewerElement != null && authorizerElement != null && approverElement != null) {
String[] reviewerValues = FormUtil.getElementPropertyValues(reviewerElement, formData);
String[] authorizerValues = FormUtil.getElementPropertyValues(authorizerElement, formData);
String[] approverValues = FormUtil.getElementPropertyValues(approverElement, formData);
String elementId = FormUtil.getElementParameterName(element);
String selectedValue = values[0];
if (selectedValue == null || selectedValue.trim().isEmpty()) {
formData.addFormError(elementId, "Approver cannot be blank");
return false;
}
if (selectedValue.equals(reviewerValues[0])
|| Arrays.asList(authorizerValues).contains(selectedValue)
|| selectedValue.equals(approverValues[0])) {
formData.addFormError(elementId, "Approver must be unique");
return false;
}
} else {
return false;
}
return true;
} catch (Exception e) {
return false;
}
}
return validate(element, formData, values);
5. Quick Validation Checklist
- Select the same user in two roles: form must fail with duplicate error.
- Select different users across roles: form must submit.
- Leave a required role empty: form must show empty-field error.
6. Security and Publishing Note
- Keep sample field IDs generic when sharing publicly.
- Do not publish real usernames, emails, internal group names, or environment-specific IDs.
7. Final Note
This validator is small but high impact: it enforces role separation before workflow execution and prevents approval design mistakes early.
Follow-up topic: Dynamic multi-level approver uniqueness (including grid or multi-select fields).