diff --git a/app/View/Components/Forms/Checkbox.php b/app/View/Components/Forms/Checkbox.php index 88f858ec9..d96e385f7 100644 --- a/app/View/Components/Forms/Checkbox.php +++ b/app/View/Components/Forms/Checkbox.php @@ -9,6 +9,10 @@ use Illuminate\View\Component; class Checkbox extends Component { + public ?string $modelBinding = null; + + public ?string $htmlId = null; + /** * Create a new component instance. */ @@ -47,6 +51,18 @@ class Checkbox extends Component */ public function render(): View|Closure|string { + // Store original ID for wire:model binding (property name) + $this->modelBinding = $this->id; + $this->htmlId = $this->id; + + // Generate unique HTML ID by prefixing with Livewire component ID if available + if ($this->id) { + $livewireId = $this->attributes?->wire('id'); + if ($livewireId) { + $this->htmlId = $livewireId.'-'.$this->id; + } + } + return view('components.forms.checkbox'); } } diff --git a/app/View/Components/Forms/Datalist.php b/app/View/Components/Forms/Datalist.php index 33e264e37..e5bbbfb5c 100644 --- a/app/View/Components/Forms/Datalist.php +++ b/app/View/Components/Forms/Datalist.php @@ -10,6 +10,10 @@ use Visus\Cuid2\Cuid2; class Datalist extends Component { + public ?string $modelBinding = null; + + public ?string $htmlId = null; + /** * Create a new component instance. */ @@ -47,11 +51,25 @@ class Datalist extends Component */ public function render(): View|Closure|string { + // Store original ID for wire:model binding (property name) + $this->modelBinding = $this->id; + if (is_null($this->id)) { $this->id = new Cuid2; + $this->modelBinding = $this->id; } + + // Generate unique HTML ID by prefixing with Livewire component ID + // This prevents duplicate IDs when multiple forms are on the same page + $livewireId = $this->attributes?->wire('id'); + if ($livewireId && $this->modelBinding) { + $this->htmlId = $livewireId.'-'.$this->modelBinding; + } else { + $this->htmlId = $this->modelBinding ?: $this->id; + } + if (is_null($this->name)) { - $this->name = $this->id; + $this->name = $this->modelBinding; } return view('components.forms.datalist'); diff --git a/app/View/Components/Forms/Input.php b/app/View/Components/Forms/Input.php index 83c98c0df..37c126c0e 100644 --- a/app/View/Components/Forms/Input.php +++ b/app/View/Components/Forms/Input.php @@ -10,6 +10,10 @@ use Visus\Cuid2\Cuid2; class Input extends Component { + public ?string $modelBinding = null; + + public ?string $htmlId = null; + public function __construct( public ?string $id = null, public ?string $name = null, @@ -43,11 +47,24 @@ class Input extends Component public function render(): View|Closure|string { + // Store original ID for wire:model binding (property name) + $this->modelBinding = $this->id; + if (is_null($this->id)) { $this->id = new Cuid2; + $this->modelBinding = $this->id; } + // Generate unique HTML ID by prefixing with Livewire component ID + // This prevents duplicate IDs when multiple forms are on the same page + $livewireId = $this->attributes?->wire('id'); + if ($livewireId && $this->modelBinding) { + $this->htmlId = $livewireId.'-'.$this->modelBinding; + } else { + $this->htmlId = $this->modelBinding ?: $this->id; + } + if (is_null($this->name)) { - $this->name = $this->id; + $this->name = $this->modelBinding; } if ($this->type === 'password') { $this->defaultClass = $this->defaultClass.' pr-[2.8rem]'; diff --git a/app/View/Components/Forms/Select.php b/app/View/Components/Forms/Select.php index 49b69136b..c0811b5bd 100644 --- a/app/View/Components/Forms/Select.php +++ b/app/View/Components/Forms/Select.php @@ -10,6 +10,10 @@ use Visus\Cuid2\Cuid2; class Select extends Component { + public ?string $modelBinding = null; + + public ?string $htmlId = null; + /** * Create a new component instance. */ @@ -40,11 +44,25 @@ class Select extends Component */ public function render(): View|Closure|string { + // Store original ID for wire:model binding (property name) + $this->modelBinding = $this->id; + if (is_null($this->id)) { $this->id = new Cuid2; + $this->modelBinding = $this->id; } + + // Generate unique HTML ID by prefixing with Livewire component ID + // This prevents duplicate IDs when multiple forms are on the same page + $livewireId = $this->attributes?->wire('id'); + if ($livewireId && $this->modelBinding) { + $this->htmlId = $livewireId.'-'.$this->modelBinding; + } else { + $this->htmlId = $this->modelBinding ?: $this->id; + } + if (is_null($this->name)) { - $this->name = $this->id; + $this->name = $this->modelBinding; } return view('components.forms.select'); diff --git a/app/View/Components/Forms/Textarea.php b/app/View/Components/Forms/Textarea.php index 3148d2566..cad85e167 100644 --- a/app/View/Components/Forms/Textarea.php +++ b/app/View/Components/Forms/Textarea.php @@ -10,6 +10,10 @@ use Visus\Cuid2\Cuid2; class Textarea extends Component { + public ?string $modelBinding = null; + + public ?string $htmlId = null; + /** * Create a new component instance. */ @@ -53,11 +57,25 @@ class Textarea extends Component */ public function render(): View|Closure|string { + // Store original ID for wire:model binding (property name) + $this->modelBinding = $this->id; + if (is_null($this->id)) { $this->id = new Cuid2; + $this->modelBinding = $this->id; } + + // Generate unique HTML ID by prefixing with Livewire component ID + // This prevents duplicate IDs when multiple forms are on the same page + $livewireId = $this->attributes?->wire('id'); + if ($livewireId && $this->modelBinding) { + $this->htmlId = $livewireId.'-'.$this->modelBinding; + } else { + $this->htmlId = $this->modelBinding ?: $this->id; + } + if (is_null($this->name)) { - $this->name = $this->id; + $this->name = $this->modelBinding; } // $this->label = Str::title($this->label); diff --git a/resources/views/components/forms/checkbox.blade.php b/resources/views/components/forms/checkbox.blade.php index 868f657f6..b291759a8 100644 --- a/resources/views/components/forms/checkbox.blade.php +++ b/resources/views/components/forms/checkbox.blade.php @@ -32,14 +32,14 @@ merge(['class' => $defaultClass]) }} wire:loading.attr="disabled" wire:click='{{ $instantSave === 'instantSave' || $instantSave == '1' ? 'instantSave' : $instantSave }}' - wire:model={{ $id }} @if ($checked) checked @endif /> + wire:model={{ $modelBinding }} id="{{ $htmlId }}" @if ($checked) checked @endif /> @else @if ($domValue) merge(['class' => $defaultClass]) }} - value={{ $domValue }} @if ($checked) checked @endif /> + value={{ $domValue }} id="{{ $htmlId }}" @if ($checked) checked @endif /> @else merge(['class' => $defaultClass]) }} - wire:model={{ $value ?? $id }} @if ($checked) checked @endif /> + wire:model={{ $value ?? $modelBinding }} id="{{ $htmlId }}" @if ($checked) checked @endif /> @endif @endif diff --git a/resources/views/components/forms/datalist.blade.php b/resources/views/components/forms/datalist.blade.php index 7f9ffefec..abdd948f9 100644 --- a/resources/views/components/forms/datalist.blade.php +++ b/resources/views/components/forms/datalist.blade.php @@ -16,7 +16,7 @@
whereStartsWith('wire:model')->first() ? $attributes->wire('model')->value() : $id)).live, + selected: @entangle(($attributes->whereStartsWith('wire:model')->first() ? $attributes->wire('model')->value() : $modelBinding)).live, options: [], filteredOptions: [], @@ -284,7 +284,7 @@
@endif -@error($id) +@error($modelBinding) diff --git a/resources/views/components/forms/input.blade.php b/resources/views/components/forms/input.blade.php index f6c86f177..13cf1faf0 100644 --- a/resources/views/components/forms/input.blade.php +++ b/resources/views/components/forms/input.blade.php @@ -27,9 +27,9 @@ @endif merge(['class' => $defaultClass]) }} @required($required) - @if ($id !== 'null') wire:model={{ $id }} @endif + @if ($modelBinding !== 'null') wire:model={{ $modelBinding }} @endif wire:dirty.class="dark:ring-warning ring-warning" wire:loading.attr="disabled" - type="{{ $type }}" @readonly($readonly) @disabled($disabled) id="{{ $id }}" + type="{{ $type }}" @readonly($readonly) @disabled($disabled) id="{{ $htmlId }}" name="{{ $name }}" placeholder="{{ $attributes->get('placeholder') }}" aria-placeholder="{{ $attributes->get('placeholder') }}" @if ($autofocus) x-ref="autofocusInput" @endif> @@ -38,19 +38,19 @@ @else merge(['class' => $defaultClass]) }} @required($required) @readonly($readonly) - @if ($id !== 'null') wire:model={{ $id }} @endif + @if ($modelBinding !== 'null') wire:model={{ $modelBinding }} @endif wire:dirty.class="dark:ring-warning ring-warning" wire:loading.attr="disabled" type="{{ $type }}" @disabled($disabled) min="{{ $attributes->get('min') }}" max="{{ $attributes->get('max') }}" minlength="{{ $attributes->get('minlength') }}" maxlength="{{ $attributes->get('maxlength') }}" - @if ($id !== 'null') id={{ $id }} @endif name="{{ $name }}" + @if ($htmlId !== 'null') id={{ $htmlId }} @endif name="{{ $name }}" placeholder="{{ $attributes->get('placeholder') }}" @if ($autofocus) x-ref="autofocusInput" @endif> @endif @if (!$label && $helper) @endif - @error($id) + @error($modelBinding) diff --git a/resources/views/components/forms/select.blade.php b/resources/views/components/forms/select.blade.php index 3c8eea25a..4871bcc9d 100644 --- a/resources/views/components/forms/select.blade.php +++ b/resources/views/components/forms/select.blade.php @@ -11,11 +11,11 @@ @endif - @error($id) + @error($modelBinding) diff --git a/resources/views/components/forms/textarea.blade.php b/resources/views/components/forms/textarea.blade.php index a1c57e775..d4fa10574 100644 --- a/resources/views/components/forms/textarea.blade.php +++ b/resources/views/components/forms/textarea.blade.php @@ -25,8 +25,8 @@ @endif @if ($useMonacoEditor) - @else @if ($type === 'password') @@ -45,34 +45,34 @@ @endif merge(['class' => $defaultClassInput]) }} @required($required) - @if ($id !== 'null') wire:model={{ $id }} @endif + @if ($modelBinding !== 'null') wire:model={{ $modelBinding }} @endif wire:dirty.class="dark:ring-warning ring-warning" wire:loading.attr="disabled" - type="{{ $type }}" @readonly($readonly) @disabled($disabled) id="{{ $id }}" + type="{{ $type }}" @readonly($readonly) @disabled($disabled) id="{{ $htmlId }}" name="{{ $name }}" placeholder="{{ $attributes->get('placeholder') }}" aria-placeholder="{{ $attributes->get('placeholder') }}"> + @disabled($disabled) @readonly($readonly) @required($required) id="{{ $htmlId }}" + name="{{ $name }}" name={{ $modelBinding }}> @else + @disabled($disabled) @readonly($readonly) @required($required) id="{{ $htmlId }}" + name="{{ $name }}" name={{ $modelBinding }}> @endif @endif - @error($id) + @error($modelBinding)