-
Notifications
You must be signed in to change notification settings - Fork 92
Description
Describe the bug
Calling validator.showSuccessLabels({...}) causes focus to jump to the first field in the provided map, even though we’re rendering success labels (not errors). This happens because showLabels() unconditionally focuses the first field when globalConfig.focusInvalidField is true, regardless of whether we’re showing errors or success labels.
This breaks UX when you want to display a success hint for a specific field while the user is typing in a different field: the caret jumps unexpectedly.
Relevant code (from library source):
showLabels(fields: ShowLabelsInterface, isError: boolean): void {
Object.keys(fields).forEach((fieldName, i) => {
const error = fields[fieldName];
const key = this.getKeyByFieldSelector(fieldName);
if (!key || !this.fields[key]) {
console.error(`Field not found. Check the field selector.`);
return;
}
const field = this.fields[key];
field.isValid = !isError;
this.clearFieldStyle(key);
this.clearFieldLabel(key);
this.renderFieldError(key, false, error);
// Problem: this runs even for success labels
if (i === 0 && this.globalConfig.focusInvalidField) {
setTimeout(() => field.elem.focus(), 0);
}
});
}To Reproduce
- Initialize JustValidate with
focusInvalidField: true. - Set up two inputs, e.g.
#aand#b. Focus and start typing into#b. - Programmatically call
validator.showSuccessLabels({ '#a': 'Looks good' }). - Observe focus moves from
#bto#a.
Minimal example:
<form id="form">
<input id="a" />
<input id="b" />
</form>
<script>
const v = new JustValidate('#form', {
focusInvalidField: true
}).addField('#a', [{
validator: (value, context) => true,
}]).addField('#b', [{
validator: (value, context) => true,
}]).onValidate((ctx) => {
// Simulate showing a success label for #a while the user is on #b
v.showSuccessLabels({
'#a': 'Looks good'
});
// Caret jumps to #a unexpectedly
});
document.getElementById('b').focus();
</script>Expected behavior
showSuccessLabels()should not move focus.- Focusing should only occur when rendering errors and only if
focusInvalidFieldistrue.
Actual behavior
- Focus jumps to the first field passed into
showSuccessLabels()wheneverfocusInvalidFieldistrue.
Screenshots
N/A (behavior is a visible focus jump/caret move).
Additional context
- The focus line is guarded only by
i === 0 && this.globalConfig.focusInvalidField, ignoringisError. - This also affects scenarios where we programmatically show success for one field based on another field’s change (common with cross-field rules).
Suggested enhancement
If desired, a separate option like focusOnSuccessLabels (default false) could be added.
In addition
The onValidate delegate does not provide a way to determine whether a field’s value has changed since the last validation. This is useful when you want to show success feedback only for fields edited since the previous successful validation.
Why this matters
- Avoids noisy success labels for untouched fields.
- Enables precise UX flows (e.g., “validate edited fields only”, show per-field success on change).
- Helps with forms that do cross-field updates without revalidating the whole form.