When a blueprint field has validate: required, Statamic shows a red * next to the field label in the Control Panel, telling the user up front which fields they must fill in.
However, when a field uses a conditional required rule — required_if, required_if_accepted, required_if_declined, required_unless, required_with, required_with_all, required_without, required_without_all — no indicator is ever shown, even when the condition is currently satisfied and the field is in fact required for a successful save.
The result is that users see a field with no required marker, try to submit, and get a validation error they had no way to anticipate. The conditional-required rules are powerful, but the UI gives the editor no feedback that they've just made a sibling field required.
Proposal
When a field's validate rules include any required_* rule, evaluate the condition reactively against the current form values and show the required indicator whenever the condition is satisfied. The indicator should appear/disappear in real time as the editor changes the dependent fields — the same way conditional-field visibility (if/unless/show_when/hide_when) already updates reactively.
Concretely, this may mean:
- Stop stripping
validate before it reaches the front-end. src/Fields/Field.php:282 currently does unset($array['validate']) inside toPublishArray(). The Vue layer needs the raw rule list to evaluate conditions client-side.
- Make
isRequired a reactive computed in the Publish field component. resources/js/components/ui/Publish/Field.vue:85 currently reads props.config.required as a static prop. It should instead compute over (a) the static required flag and (b) any required_* rules evaluated against the live container values.
- Add a client-side evaluator for the
required_ family*, parallel to the existing ShowField evaluator used for conditional visibility (Field.vue:140-150). The infrastructure for reading sibling values reactively already exists — this is the same mechanism, applied to a different output.
- Server-side
isRequired() can stay as-is for the rules-collection use cases internal to the framework; the reactive change is purely a UI affordance. Or, optionally, accept a context parameter so it can evaluate conditional rules against a known data set when needed.
Alternatives Considered
- Treat any
required_ rule as "always required" in the UI. Easy server-side patch, but it's worse than the current behavior — it lies to the editor by showing * even when the condition isn't met.
- Custom fieldtype wrapper / service-provider override. Workable for the static-asterisk case (option above) but cannot deliver the reactive behavior, because the Vue components and
toPublishArray()'s unset('validate') aren't reachable from user code without forking core.
- Render the asterisk in field instructions / a custom label. Hacky, doesn't compose, and addons / blueprint authors shouldn't have to reimplement a core affordance.
Additional context
The rules that should be considered conditional-required: required_if, required_if_accepted, required_if_declined, required_unless, required_with, required_with_all, required_without, required_without_all. Laravel's Illuminate\Validation\Concerns\ValidatesAttributes is the source of truth for their semantics — the client-side evaluator should mirror those.
This pairs naturally with the existing conditional-visibility system: a field that's only shown when X has a value is often also required only when X has a value, and right now editors get the visibility cue but no requiredness cue.
When a blueprint field has
validate: required, Statamic shows a red*next to the field label in the Control Panel, telling the user up front which fields they must fill in.However, when a field uses a conditional required rule —
required_if,required_if_accepted,required_if_declined,required_unless,required_with,required_with_all,required_without,required_without_all— no indicator is ever shown, even when the condition is currently satisfied and the field is in fact required for a successful save.The result is that users see a field with no required marker, try to submit, and get a validation error they had no way to anticipate. The conditional-required rules are powerful, but the UI gives the editor no feedback that they've just made a sibling field required.
Proposal
When a field's
validaterules include anyrequired_*rule, evaluate the condition reactively against the current form values and show the required indicator whenever the condition is satisfied. The indicator should appear/disappear in real time as the editor changes the dependent fields — the same way conditional-field visibility (if/unless/show_when/hide_when) already updates reactively.Concretely, this may mean:
validatebefore it reaches the front-end. src/Fields/Field.php:282 currently doesunset($array['validate'])insidetoPublishArray(). The Vue layer needs the raw rule list to evaluate conditions client-side.isRequireda reactivecomputedin the Publish field component. resources/js/components/ui/Publish/Field.vue:85 currently readsprops.config.requiredas a static prop. It should instead compute over (a) the staticrequiredflag and (b) anyrequired_* rules evaluated against the live container values.required_family*, parallel to the existingShowFieldevaluator used for conditional visibility (Field.vue:140-150). The infrastructure for reading sibling values reactively already exists — this is the same mechanism, applied to a different output.isRequired()can stay as-is for the rules-collection use cases internal to the framework; the reactive change is purely a UI affordance. Or, optionally, accept a context parameter so it can evaluate conditional rules against a known data set when needed.Alternatives Considered
required_rule as "always required" in the UI. Easy server-side patch, but it's worse than the current behavior — it lies to the editor by showing*even when the condition isn't met.toPublishArray()'sunset('validate')aren't reachable from user code without forking core.Additional context
The rules that should be considered conditional-required:
required_if,required_if_accepted,required_if_declined,required_unless,required_with,required_with_all,required_without,required_without_all. Laravel'sIlluminate\Validation\Concerns\ValidatesAttributesis the source of truth for their semantics — the client-side evaluator should mirror those.This pairs naturally with the existing conditional-visibility system: a field that's only shown when X has a value is often also required only when X has a value, and right now editors get the visibility cue but no requiredness cue.