Be part of JetBrains PHPverse 2026 on June 9 – a free online event bringing PHP devs worldwide together.

PttRulez's avatar
Level 21

Problems updating nested components in livewire

I have problems updating nested components in livewire. For example. Here is a part of a form component:

<section>
      <x-input-field wire:model="foodName" :errorMessages="$errors->get('foodName')"
                label="{{ __('Food Name') }}"  placeholder="{{ __('type food name') }}" />
</section>

Here is the code of nested input component. It has another nested with errors. I'm not sure if you need it's code

@props([
    'autoComplete' => 'off',
    'label' => 'label',
    'required' => false,
    'type' => 'text',
    'errorMessages' => [],
    'step' => '.1',
])

<label {{ $attributes->merge(['class' => 'form-control w-full']) }}>
  <div class='label'>
    <span class='label-text'>{{ $label }}</span>
  </div>
  <input class="input input-bordered w-full" type='{{ $type }}'
    @isset($step)
     step="{{ $step }}"
   @endif autoComplete='{{ $autoComplete }}'
    @required($required) />
  <x-input-error :messages="$errorMessages" class="mt-2" />
</label>

So the problem is that this input is not updated after submitting form. In submit component I update $foodName property but it's not reset visually, it stays inside input. I tried it with just simple input and it worked correctly. First input has empty value after submitting form while another the nested component stays filled

<input wire:model="foodName" /> // this one works as expected

<section>
      <x-input-field wire:model="foodName" :errorMessages="$errors->get('foodName')"
                label="{{ __('Food Name') }}"  placeholder="{{ __('type food name') }}" />
</section>
0 likes
1 reply
LaryAI's avatar
Level 58

The issue you're experiencing with the Livewire component not updating the nested input field is likely due to the fact that the wire:model directive is not being applied directly to the <input> element within your custom Blade component. Livewire requires the wire:model directive to be directly on the input element to properly bind the data.

To resolve this, you need to ensure that the wire:model directive is passed down to the actual <input> element within your custom component. Here's how you can modify your component to achieve this:

  1. Update your Blade component to accept additional attributes and pass them to the <input> element.

  2. Use the @props directive to allow passing of attributes like wire:model.

Here's how you can modify your component:

@props([
    'autoComplete' => 'off',
    'label' => 'label',
    'required' => false,
    'type' => 'text',
    'errorMessages' => [],
    'step' => '.1',
])

<label {{ $attributes->merge(['class' => 'form-control w-full']) }}>
  <div class='label'>
    <span class='label-text'>{{ $label }}</span>
  </div>
  <input {{ $attributes->whereStartsWith('wire:model') }} class="input input-bordered w-full" type='{{ $type }}'
    @isset($step)
     step="{{ $step }}"
   @endif autoComplete='{{ $autoComplete }}'
    @required($required) />
  <x-input-error :messages="$errorMessages" class="mt-2" />
</label>

In this updated version, the {{ $attributes->whereStartsWith('wire:model') }} line ensures that any wire:model attribute passed to the component is applied directly to the <input> element.

Now, when you use your component, you can pass the wire:model directive like this:

<section>
    <x-input-field wire:model="foodName" :errorMessages="$errors->get('foodName')"
                   label="{{ __('Food Name') }}" placeholder="{{ __('type food name') }}" />
</section>

This should ensure that the foodName property is properly bound to the input field, and any updates to foodName will reflect in the input field as expected.

Please or to participate in this conversation.