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

SigalZ's avatar

Nested Livewire component tries to get properties from parent

Using Laravel 10, Livewire 3

I have a component that has a child component.

For some reason, the inputs on the child component blade try to get the properties from the parent component instead of the child component.

My parent component NewOrdersComponent:

<?php

namespace App\Livewire\Admin\Order;

use Livewire\Component;
use Illuminate\Support\Facades\Auth;
use App\Jobs\OrderUpdatedJob;
use App\Jobs\PaymentReminderJob;
use App\Models\Order;

class NewOrdersComponent extends Component
{ 
   public $orders;

   public function mount()
   {   
         $this->orders = Order::where(function($q) {
               $q->where('status', 1)
                  ->orWhere('status', 11);
               })
               ->get();      
   }

   public function render()
   {
      return view('livewire.admin.order.new-orders-component')->extends('layouts.admin.master');
   }
}

The blade:

<div>

@if($orders->count())
    @foreach($orders as $order)
    <div class="table-responsive">
        <table class="table table-bordered table-sm">
            <thead>
                <tr>
                    <th>Coffee</th>
                    <th>Grind</th>
                    <th>Weight</th>
                    <th>Qty</th>
                    @can('edit orders')
                    <th></th>                                   
                    @endcan
                </tr>
            </thead>
            <tbody>
            @foreach($order->orderItems as $orderItem)                            
                <livewire:admin.order.order-item-component :$orderItem />
            @endforeach
            </tbody>
        </table>
    </div>
    @endforeach
@else
    <p>Bummer, there are no new orders</p>
@endif

</div>

The child component OrderItemComponent:

<?php

namespace App\Livewire\Admin\Order;

use Livewire\Component;
use App\Models\OrderItem;

class OrderItemComponent extends Component
{ 
   public $orderItem;
   public $prepMethod;
   public $qty;

    public function mount(OrderItem $orderItem)
    {
        $this->orderItem = $orderItem;
        $this->prepMethod = $orderItem->prep_method;
        $this->qty = $orderItem->qty;
    }

    public function updatePrepMethod()
    {
        $this->authorize('edit orders', Order::class);

        $this->orderItem->update(['prep_method' => $this->prepMethod]);

        session()->flash('alert', 'The preperation method has been udpated.');

        $this->redirect(OrderItemComponent::class);
    }

    public function updateQty()
    {
        $this->authorize('edit orders', Order::class);

        $this->orderItem->update(['qty' => $this->qty]);

        session()->flash('alert', 'The item quantity has been udpated.');

        $this->redirect(OrderItemComponent::class);
    }

    public function render()
    {
        return view('livewire.admin.order.order-item-component');
    }
}

The blade:

<div>
    
    <tr wire:key="{{ $orderItem->id }}">
        <td>{{ $orderItem->coffee->name }}</td>
        <td>                                        
            @can('edit orders')
            <form method="post" wire:submit.prevent="updatePrepMethod()" class="prepMethodForm">
                @csrf
                @method('PATCH')
                
                <div class="form-group">
                    <select name="prep_method" class="form-control" wire:model="prepMethod">
                        <option value="Beans">Beans (Not Ground)</option>
                        <option value="Espresso">Espresso</option>
                        <option value="Filter">Filter</option>
                        <option value="Moka Pot">Moka Pot</option>
                        <option value="Plunger">Plunger</option>
                        <option value="Turkish">Turkish</option>
                    </select>
                </div>
                <button type="submit" class="btn bg-gradient-success btn-sm">Save</button>                                    
            </form>
            @else
            {{ $prepMethod }}
            @endif         
        </td>
        <td>{{ $orderItem->weight }}</td>
        <td>
            @if(auth()->user()->can('edit orders'))
            <form role="form" class="form" method="post" wire:submit.prevent="updateQty()" novalidate>
                @csrf
                @method('PATCH')
                <div class="form-group">
                    <input type="number" name="qty" class="form-control" wire:model="qty">
                </div>
                
                <div class="form-group text-right">
                    <button type="submit" class="btn bg-gradient-success btn-sm">Save</button>                
                </div>                
            </form>            
            @else
            {{ $qty }}
            @endif
        </td>
        @can('edit orders')                
        <td>
            <form method="post" class="form" wire:submit.prevent="delete()">
                @csrf
                @method('DELETE')
                <button type="submit" class="btn btn-danger btn-xs"><span class="fa fa-trash"></span></button>
            </form>
        </td>                                        
        @endcan
    </tr>

</div>

When I run the page, I get these errors in firebug:

Livewire: [wire:model="prepMethod"] property does not exist on component: [admin.order.new-orders-component] livewire.js:7607:22

Livewire: [wire:model="qty"] property does not exist on component: [admin.order.new-orders-component] livewire.js:7607:22

I don't understand why it tries to get qty and prepMethod from NewOrdersComponent and not OrderItemComponent?

0 likes
10 replies
Snapey's avatar

make sure you add key to the loop including the child component

watch Calebs videos, there is one specifically on nesting components

SigalZ's avatar

@Snapey Thanks, I do add a key. I am going to try it all line by line and will post here if I find a solution.

Snapey's avatar
Snapey
Best Answer
Level 122

@SigalZ watch the video where caleb says definitely put the key on the parent not in the child

Also, your child element should have <tr> as its root node, not a div

1 like
SigalZ's avatar

@Snapey I am giving this a break and moving on, I will try again with your suggestions. Thank you, I will update this post when I try again.

SigalZ's avatar

@Snapey as usual, you save my day. Can I adopt you??? ;) Thank you. what helped is I removed the "div" element from the child component.

My parent blade now looks like this:

<div class="table-responsive">
                        <table class="table table-bordered table-sm">
                            <thead>
                                <tr>
                                    <th>Coffee</th>
                                    <th>Grind</th>
                                    <th>Weight</th>
                                    <th>Qty</th>
                                    @can('edit orders')
                                    <th></th>                                   
                                    @endcan
                                </tr>
                            </thead>
                            <tbody>
                            @foreach($order->orderItems as $item)                               
                                <livewire:admin.order.order-item-component :orderItem="$item" :key="$item->id" />
                            @endforeach
                            </tbody>
                        </table>
                    </div>

The child component (order-item-component):

    <tr wire:key="{{ $orderItem->id }}">
        <td>{{ $orderItem->coffee->name }}</td>
        <td>
            @if(auth()->user()->can('edit orders'))
            <form method="post" wire:submit.prevent="updatePrepMethod()" class="prepMethodForm">
                @csrf
                @method('PATCH')
                
                <div class="form-group">
                    <select class="form-control" wire:model="prepMethod">
                        <option value="Beans">Beans (Not Ground)</option>
                        <option value="Espresso">Espresso</option>
                        <option value="Filter">Filter</option>
                        <option value="Moka Pot">Moka Pot</option>
                        <option value="Plunger">Plunger</option>
                        <option value="Turkish">Turkish</option>
                    </select>
                </div>
                <button type="submit" class="btn bg-gradient-success btn-sm">Save</button>                                    
            </form>
            @else
            {{ $orderItem->prep_method }}
            @endif
        </td>
        <td>{{ $orderItem->weight }}</td>
        <td>
            @if(auth()->user()->can('edit orders'))
            <form role="form" class="form" method="post" wire:submit.prevent="updateQty()" novalidate>
                @csrf
                @method('PATCH')
                <div class="form-group">
                    <input type="number" name="qty" class="form-control" wire:model="qty">
                </div>
                
                <div class="form-group text-right">
                    <button type="submit" class="btn bg-gradient-success btn-sm">Save</button>                
                </div>                
            </form>            
            @else
            {{ $qty }}
            @endif
        </td>
        @can('edit orders')                
        <td>
            <form method="post" class="form" wire:submit.prevent="delete()">
                @csrf
                @method('DELETE')
                <button type="submit" class="btn btn-danger btn-xs"><span class="fa fa-trash"></span></button>
            </form>
        </td>                                        
        @endcan
    </tr>

Please or to participate in this conversation.