, so screen
readers get one accessible name from the inner form-control label,
not two competing ones. Ignored in multi mode, which uses $label for
the left column.
checked: explicit checked-state override. When passed (non-null), it
wins over the old-input / $item fallback below. Needed for contexts
(like Livewire) where the source of truth is neither the session's old
input nor a bound Eloquent model but a live component property.
input_div_class default: skip the col-md-offset-3 when there's a
left-hand column of any kind (multi with $label, or single with
$section_label). Keeping the grid classes centralized here means a
future Bootstrap / AdminLTE upgrade only has to touch this file, not
every callsite. Note: Blade evaluates @props defaults twice (once via
extractPropNames before caller attrs are bound, once when applying
defaults after). The `?? null` guards against "undefined variable" on
the first pass, isset() is inherently safe against undefined vars,
is_array() is not. --}}
@props([
'name' => null,
'item' => null,
'label' => null,
'options' => null,
'selected' => null,
'value' => '1',
'required' => null,
'disabled' => false,
'help_text' => null,
'help_html' => null,
'help_icon' => null,
'info_tooltip_text' => null,
'section_label' => null,
'checked' => null,
'input_div_class' => ((is_array($options ?? null) && isset($label)) || isset($section_label)) ? 'col-md-8' : 'col-md-8 col-md-offset-3',
])
@php
// Multi-checkbox mode kicks in when the caller supplies an $options map;
// otherwise this renders as a single boolean checkbox.
$is_multi = is_array($options);
// Old-input aware check-state. On a fresh render, session()->hasOldInput()
// is false, so we fall back to the model (or supplied :selected). On a
// validation-failure redisplay, hasOldInput() is true and we trust the
// (possibly missing) old value: an unchecked box comes back correctly
// unchecked instead of falling through to the stale $item->{$name}.
$is_redisplay = session()->hasOldInput();
if (! $is_multi) {
// Explicit :checked wins over any implicit source. Otherwise fall
// back to old input on redisplay, then to the bound $item attribute.
$single_checked = $checked !== null
? (bool) $checked
: ($is_redisplay
? (bool) old($name)
: (bool) ($item?->{$name} ?? false));
// Helper::checkIfRequired dereferences $item statically via $item::rules(),
// so it needs a real class/object. Fall back to false when no model was
// supplied (transient forms have no persistent model).
$really_required = $required ?? ($item ? Helper::checkIfRequired($item, $name) : false);
} else {
// For multi mode, callers can pass :selected as an array of currently-
// selected values, a comma-joined string (common when the model stores
// it that way, e.g. Setting's modellist_displays), or a callable
// (value): bool for per-value predicates. When :selected is omitted
// the same fallback is applied to $item->{$name}.
if ($selected === null) {
$selected = $item?->{$name};
}
if (is_string($selected)) {
$selected = $selected === '' ? [] : array_map('trim', explode(',', $selected));
}
$old_values = is_array(old($name)) ? old($name) : [];
$is_checked = function ($value) use ($is_redisplay, $old_values, $selected) {
if ($is_redisplay) {
return in_array($value, $old_values);
}
if (is_callable($selected)) {
return (bool) $selected($value);
}
return in_array($value, is_array($selected) ? $selected : []);
};
}
$errors_class = $errors->has($name) ? ' has-error' : '';
@endphp