Home > Software engineering >  Livewire - Multiple root elements detected
Livewire - Multiple root elements detected

Time:02-25

I'm creating a table, whose rows are wrapped inside a livewire component

<div >
    <div >
        <table >
            <thead>
                <tr>
                    <th>Nombre del Riesgo</th>
                    <th>Información</th>
                    <th>Dueño del Riesgo</th>
                    <th>Costo Adicional</th>
                    <th>Prevención</th>
                </tr>
            </thead>
            <tbody>
                <div>
                    @foreach($risks as $risk)
                        <livewire:risk-row :risk="$risk"/>
                    @endforeach
                </div>
            </tbody>
        </table>
    </div>
</div>

But in the row component, whenever I change an input, or select something from a dropdown select, the component is not re rendering.

I was wondering why this could be happening. So I opened my console and saw:

Livewire: Multiple root elements detected. This is not supported. See docs for more information https://laravel-livewire.com/docs/2.x/troubleshooting#root-element-issues <div wire:id=​"6CNMP1hiBR3Qy7IbmfbQ">​ ​</div>​
value @ index.js:85
Component @ index.js:27
(anonymous) @ index.js:88
value @ index.js:87
(anonymous) @ schedule:432

Here's the component blade file

<div>
    <tr>
        <td>{{ $risk['name'] }}</td>
        <td>
            <div><strong>Proceso: </strong>{{ $risk['process']['name'] }}</div>
            <div><strong>Frecuencia: <span >{{ $risk['frequency_label'] }}</span></strong></div>
            <div><strong>Impacto: </strong><span >{{ $risk['impact_label'] }}</span></div>
            <div><strong>Riesgo: </strong><span >{{ $risk['risk_label'] }}</span></div>
        </td>
        <td>
            <select name="owner" id="owner"  wire:change="test">
               @foreach(App\Models\Risk::OWNERS as $owner)
                    <option value="{{ $owner['id'] }}">{{ $owner['name'] }}</option>
               @endforeach
            </select>
            {{ $owner_id }}
        </td>
        <td>
            <select name="owner" id="owner" >
                @foreach(App\Models\Risk::COSTS as $cost)
                    <option value="{{ $cost['id'] }}">{{ $cost['name'] }}</option>
                @endforeach
            </select>
        </td>
        <td>
            <select name="owner" id="owner" >
                @foreach(App\Models\Risk::PREVENTIONS as $prevention)
                    <option value="{{ $prevention['id'] }}">{{ $prevention['name'] }}</option>
                @endforeach
            </select>
        </td>
    </tr>
</div>

Is there any workaround for this?

CodePudding user response:

When using livewire inside a foreach, you need to add a key.

<tbody>
    @foreach ($risks as $risk)
        <livewire:risk-row :risk="$risk" :wire:key="$loop->index">
    @endforeach
</tbody>

Also, you could use the <tr> as the root element and avoid having <div> inside the <tbody>.

Finally, you're using a lot of id and name attributes that repeat over and over. You should not have duplicate ids. As for the name attributes, you can use the array notation.

<tr>
    <td>{{ $risk['name'] }}</td>
    <td>
        <div><strong>Proceso: </strong>{{ $risk['process']['name'] }}</div>
        <div><strong>Frecuencia: <span >{{ $risk['frequency_label'] }}</span></strong></div>
        <div><strong>Impacto: </strong><span >{{ $risk['impact_label'] }}</span></div>
        <div><strong>Riesgo: </strong><span >{{ $risk['risk_label'] }}</span></div>
    </td>
    <td>
        <select name="owner[]"  wire:change="test">
           @foreach(App\Models\Risk::OWNERS as $owner)
                <option value="{{ $owner['id'] }}">{{ $owner['name'] }}</option>
           @endforeach
        </select>
        {{ $owner_id }}
    </td>
    <td>
        <select name="cost[]" >
            @foreach(App\Models\Risk::COSTS as $cost)
                <option value="{{ $cost['id'] }}">{{ $cost['name'] }}</option>
            @endforeach
        </select>
    </td>
    <td>
        <select name="prevention[]" >
            @foreach(App\Models\Risk::PREVENTIONS as $prevention)
                <option value="{{ $prevention['id'] }}">{{ $prevention['name'] }}</option>
            @endforeach
        </select>
    </td>
</tr>
  • Related