digital-creative/conditional-container
Conditional Container for Laravel lets you render Blade components or HTML containers only when given conditions are met, keeping your views clean and readable. It supports flexible closures, gate checks, and inline conditionals for cleaner templates.
1. Verify what you're actually installing. The metadata is inconsistent: the repo, source tree, and release notes describe a Laravel Nova field (ConditionalContainer::make([...])->dependsOn(...)), while one blurb describes a plain Blade component. Trust the source. Open composer.json, read the require block, and confirm it matches your pinned Nova, Laravel, and PHP versions. If you're not on Nova, close the tab.
2. Install and pin the version.
composer require digital-creative/conditional-container
Then freeze it in composer.json:
"digital-creative/conditional-container": "1.4.3"
Last release was May 2022, single maintainer. You want a deliberate version, not whatever ^1.4 resolves to six months from now.
3. Wire the trait into the resource. The container renders without this, but it won't react to anything:
use DigitalCreative\ConditionalContainer\HasConditionalContainer;
class Customer extends Resource
{
use HasConditionalContainer;
}
4. First use case: something boring and internal. Pick one field that only matters in one state. Show VAT fields only for business accounts:
public function fields(NovaRequest $request)
{
return [
Select::make('Account Type')
->options([
'individual' => 'Individual',
'business' => 'Business',
])
->rules('required'),
ConditionalContainer::make([
Text::make('Company Name'),
Text::make('VAT Number'),
])->dependsOn('account_type', 'business'),
];
}
5. Where to look first.
src/ConditionalContainer.php — the real public surface; the README lags behind it.src/HasConditionalContainer.php — what the trait actually touches on your resource.1.4.3 release note ("Check if field is shown on update") — proof that update-page visibility was genuinely broken. Test create and update explicitly.dist/js/ — what Nova loads; the first place to look when behaviour looks wrong on screen but right in the field list.6. Smoke test all four states before writing the second container. Create with condition false, create with it true, update flipping true, update flipping false. Persist a record each time and check what actually lands in the DB.
Keep the controlling field outside and above the container. Always a top-level sibling, never nested inside another container:
Select::make('Status')->options(Status::options()),
ConditionalContainer::make([
Textarea::make('Refund Reason'),
])->dependsOn('status', Status::Refunded->value),
Field ordering is load-bearing — a controller declared after the container may resolve against an undefined value on first render.
One container per logical state, not per field. Group everything that shares a visibility rule:
ConditionalContainer::make([
DateTime::make('Approved At'),
BelongsTo::make('Approved By', 'approver', User::class),
Textarea::make('Approval Notes'),
])->dependsOn('approved', true),
Prefer several small containers over one container with a baroque multi-value condition. Every rule you add multiplies the QA matrix.
Use closures for anything the scalar comparison can't express. Multi-value membership, request-dependent visibility, etc.:
ConditionalContainer::make([...])
->dependsOn('status', fn ($value) => in_array($value, ['refunded', 'partially_refunded'], true)),
Confirm the closure signature against src/ConditionalContainer.php first — this is the API most likely to differ from your assumption. And remember closures evaluate server-side; they don't re-run when a user flips a select in the browser without a round-trip.
Scope containers to forms only. Visibility is meaningless on index and detail views and produces confusing empty cells:
ConditionalContainer::make([...])
->dependsOn('status', 'refunded')
->onlyOnForms(), // or ->hideFromIndex()->hideFromDetail()
Always pair visibility with server-side validation. Visibility is UX, rules are truth. The container must never be the reason a field goes unvalidated:
Textarea::make('Refund Reason')
->rules('required_if:status,refunded'),
Use sometimes / nullable in the underlying rules so hidden fields don't fail validation when the condition is false. Write two feature tests as the guardrail: condition false with the dependent field populated, and condition true with the field empty.
Extract shared containers into resource methods. When three resources need the same billing block, return it from one place:
private function billingContainer(): ConditionalContainer
{
return ConditionalContainer::make([...])->dependsOn('account_type', 'business');
}
This is also your migration seam when you swap to native Nova dependent fields or a fork — one method per resource, not a grep across the codebase.
Adopt one resource per PR. Small, reviewable, revertible. Start with a read-only internal resource, hold it a sprint, then replicate.
A 2022 release against a current Nova major is your highest-probability failure. Pin the version, test the pilot against the exact production matrix, and add "re-test every conditional-container resource" to your Nova upgrade checklist. Budget a fork-and-patch allowance before you need it — the exit cost is hours, but only if someone on the team can read the field-rendering code.
Hidden does not mean absent. Depending on how visibility is implemented (render vs. unmount), hidden children may still submit, still appear in the request payload, and still be validated. Never let a container gate permissions, skip validation, or protect sensitive data.
Visibility is not access control. If an operator must not see a field, that's a policy question. Policies and field-level authorization remain authoritative — no exceptions.
Nested containers, Repeater, and Builder are the sharp edge. Each nesting level multiplies the number of field instances the visibility logic has to track. Test every field type you actually use on day one — not just Text and Select. If a nested case misbehaves, hoist it to a top-level container rather than debugging the nesting.
Missing HasConditionalContainer looks like a JS bug. The container renders, fields appear, but nothing ever toggles. Check the trait first when "it just doesn't react."
Debugging: inspect the field list, not the browser. Temporarily dd($this->fields(request())) in the resource to see how the container resolves server-side. If the field list is correct and the screen is wrong, you're looking at an asset problem — check dist/js/ and any other Nova package injecting conflicting scripts.
Update-page visibility was a real bug. If you're on an earlier 1.4.x, upgrade to 1.4.3 or expect conditions to behave differently when editing an existing record. Test both paths for every container you ship.
Closures are not reactive. Server-evaluated conditions won't re-run on client-side field changes without a round-trip. If you need instant reactivity across many fields, this package may be the wrong tool — consider native Nova dependent fields or a small custom field.
Zero runtime cost, near-zero maintenance cost — until an upgrade. This is admin UI, not a request path. It won't touch API latency or database load. All of the lifecycle risk is concentrated in the Nova/PHP upgrade moment, so schedule compatibility review against that event, not a calendar cadence.
Prefer native when it's equivalent. If Nova's built-in dependent-field behaviour already covers your top two or three forms, you're adding a dependency for the same UX. Reach for this package where native logic gets ugly — many fields sharing one rule, multi-value conditions, fallback slots — not as a default.
How can I help you explore Laravel packages today?