Nicho's avatar
Level 1

Laravel Livewire : livewire multiple root elements detected

Hello, i'm currently developing a website using laravel livewire

I'm creating a multi-site form page and on the inside of the multi-site form page, there's a dynamic dropdown on it.

The problem that i had is, when the value is filled it won't store the value/data into the database, and it sent me an error message when i inspect it

The error message is : livewire multiple root elements detected

How do i fix this problem??

The livewire model :

<?php

namespace App\Http\Livewire;

use Livewire\Component;
use App\Models\Kredit;
use App\Models\Biaya;
use App\Models\Produk;
use App\Models\Promo;
use App\Models\Motorcycle;
use App\Models\MotorcycleBrand;
use App\Models\Domisili;

class KreditMulti extends Component
{
    public $biaya_id;
    public $produk_id;
    public $promo_id;
    public $motorcycle_id;
    public $motorcycle_brand_id;
    public $domisili_id;
    public $kredit_nik;
    public $kredit_name;
    public $kredit_phone;
    public $kredit_phone2;
    public $kredit_vehicle;
    public $kredit_plan;
    public $kredit_desc;

    public $brand_id;

    public $totalSteps = 2;
    public $currentStep = 1;

    public function mount()
    {
        $this->currentStep = 1;
    }

    public function render()
    {
        $domisilis = Domisili::all();
        // $motorcycles = Motorcycle::all();
        // $motorcycle_brands = MotorcycleBrand::all();

        //for the dynamic dropdown
        if($this->brand_id){
            $motorcycle_brands = MotorcycleBrand::where('motorcycle_id', $this->brand_id)->get();
        } else {
            $motorcycle_brands = [];
        }

        return view('livewire.kredit-multi',
        ['domisilis'=>$domisilis])
                ->withMotorcycles(Motorcycle::all())
				->with('motorcycle_brands', $motorcycle_brands);
    }

    public function increaseStep(){
        $this->resetErrorBag();
        $this->validateData();
        $this->currentStep++;
        if($this->currentStep > $this->totalSteps){
            $this->currentStep = $this->$totalSteps;
        }
    }

    public function decreaseStep(){
        $this->resetErrorBag();
        $this->currentStep--;
        if($this->currentStep < 1){
            $this->currentStep = 1;
        }
    }

    public function validateData(){
        if($this->currentStep == 1){
            $this->validate([
                'biaya_id'=>'required',
                'promo_id'=>'required',
                'domisili_id'=>'required',
                'kredit_nik'=>'required|numeric|digits:16',
                'kredit_name'=>'required',
                'kredit_phone'=>'required|numeric|digits_between:10,15',
                'kredit_phone2'=>'nullable|numeric|digits_between:10,15'
            ]);
        }
    }

    public function createkredit(){
        if($this->currentStep == 2){
            $this->validate([
                'produk_id'=>'required',
                'motorcycle_id'=>'required',
                'motorcycle_brand_id'=>'required',
                'kredit_vehicle'=>'required',
                'kredit_plan'=>'required|numeric',
                'kredit_desc'=>'nullable'
            ]);
        }

        $values = array(
            "biaya_id" => $this->biaya_id,
            "produk_id"=> $this->produk_id,
            "promo_id"=> $this->promo_id,
            "motorcycle_id"=> $this->motorcycle_id,
            "motorcycle_brand_id"=>$this->motorcycle_brand_id,
            "domisili_id"=> $this->domisili_id,
            "kredit_nik"=> $this->kredit_nik,
            "kredit_name"=> $this->kredit_name,
            "kredit_phone"=> $this->kredit_phone,
            "kredit_phone2"=> $this->kredit_phone2,
            "kredit_vehicle"=> $this->kredit_vehicle,
            "kredit_plan"=> $this->kredit_plan,
            "kredit_desc"=> $this->kredit_desc,
            "brand_id"=> $this->brand_id
        );

        Kredit::insert($values);
        $this->reset();
        $this->currentStep = 1;

        return redirect()->to('/kredit');
    }
}

The livewire blade php :

<div>
    {{-- Because she competes with no one, no one can compete with her. --}}
    <form wire:submit.prevent="createkredit">
        {{--Step 1,3152021502002002--}}
        @if ($currentStep == 1)
        <div class="form-group">
            <label>NIK</label>
            <input type="text" required class="form-control @error('kredit_nik') is-invalid @enderror" id="kredit_nik" name="kredit_nik" class="form-control" autocomplete="off" value="{{old('kredit_nik')}}" placeholder="Contoh : 3152021502002002" wire:model="kredit_nik">
        </div>
        @error('kredit_nik') 
            <div class="alert alert-danger">{{ $message }}</div>
        @enderror
        <br>
        <div class="form-group">
            <label>Nama Lengkap</label>
            <input type="text" required class="form-control @error('kredit_name') is-invalid @enderror" id="kredit_name" name="kredit_name" class="form-control" autocomplete="off" value="{{old('kredit_name')}}" placeholder="Contoh : Nathanael Budiman" wire:model="kredit_name">
        </div>
        @error('kredit_name') 
            <div class="alert alert-danger">{{ $message }}</div>
        @enderror
        <br>
        <div class="form-group">
            <label>Nomor Telepon 1</label>
            <input type="text" required class="form-control @error('kredit_phone') is-invalid @enderror" id="kredit_phone" name="kredit_phone" class="form-control" autocomplete="off" value="{{old('kredit_phone')}}" placeholder="Contoh : 0813 8776 5887" wire:model="kredit_phone">
        </div>
        @error('kredit_phone') 
            <div class="alert alert-danger">{{ $message }}</div>
        @enderror
        <br>
        <div class="form-group">
            <label>Nomor Telepon 2 (Optional)</label>
            <input type="text" class="form-control @error('kredit_phone2') is-invalid @enderror" id="kredit_phone2" name="kredit_phone2" class="form-control"autocomplete="off" value="{{old('kredit_phone2')}}" placeholder="Contoh : 0813 8776 5887" wire:model="kredit_phone2">
        </div>
        @error('kredit_phone2') 
            <div class="alert alert-danger">{{ $message }}</div>
        @enderror
        <br>
        <div class="form-group">
            <label>Kota Domisili</label>
            <input type="text" required class="form-control @error('domisili_id') is-invalid @enderror" list="domisiliList" id="domisili_id" name="domisili_id" class="form-control" autocomplete="off" value="{{old('domisili_id')}}" placeholder="Contoh : Jakarta Pusat" wire:model="domisili_id">
            <datalist id="domisiliList" name="domisili_id">
                @foreach ($domisilis as $domisili)
                    <option value="{{$domisili->domisili_name}}">{{$domisili->domisili_name}}</option>
                @endforeach
            </datalist>
        </div>
        @error('domisili_id') 
            <div class="alert alert-danger">{{ $message }}</div>
        @enderror
        <br>
        <div class="form-group">
            <label for="biaya_id">Jenis Pembiayaan</label>
            <select class="form-control" name="biaya_id" id="biaya_id" wire:model="biaya_id">
                <option value="">--</option>
                <option value="1" {{old('biaya') == 1 ? 'selected' : ''}}>Konvensional</option>
            </select>
        </div>
        @error ('biaya_id')
            <div class="alert alert-danger">{{ $message }}</div>                                    
        @enderror
        <br>
        <div class="form-group">
            <label for="promo_id">Mengetahui Informasi Promo Dari</label>
            <select class="form-control" name="promo_id" id="promo_id" wire:model="promo_id">
                <option value="">--</option>
                <option value="1" {{old('promo_id') == 1 ? 'selected' : ''}}>Media Sosial</option>
                <option value="2" {{old('promo_id') == 2 ? 'selected' : ''}}>Website</option>
                <option value="3" {{old('promo_id') == 3 ? 'selected' : ''}}>Keluarga/Teman</option>
                <option value="4" {{old('promo_id') == 4 ? 'selected' : ''}}>SMS</option>
                <option value="5" {{old('promo_id') == 5 ? 'selected' : ''}}>Lainnya</option>
            </select>
        </div>
        @error ('promo_id')
            <div class="alert alert-danger">{{ $message }}</div>                                    
        @enderror
        <br>
        @endif

        {{--Step 2--}}
        @if ($currentStep == 2)
            
        <div class="form-group">
            <label for="produk">Jenis Produk</label>
            <select class="form-control" name="produk_id" id="produk_id" wire:model="produk_id">
                <option value="">--</option>
                <option value="1" {{old('produk_id') == 1 ? 'selected' : ''}}>Motor Baru</option>
                <option value="2" {{old('produk_id') == 2 ? 'selected' : ''}}>Motor Bekas</option>
            </select>
        </div>
        @error ('produk_id')
            <div class="alert alert-danger">{{ $message }}</div>                                    
        @enderror
        <br>

        <!--Begin for the dynamic dropdown-->
        <div class="form-group row">
            <label for="motorcycle" class="col-md-4">Merek motor</label>
            <div class="col-md-6">
                <select wire:model="brand_id" class="form-control">
                    <option value="" selected>Choose Motor</option>
                    @foreach ($motorcycles as $m)
                        <option value="{{$m->id}}">{{$m->motorcycle_name}}</option>
                    @endforeach
                </select>
            </div>
        </div>
        <br>
        @if (count($motorcycle_brands) > 0)
            <div class="form-group row">
                <label for="motorcycle_brand" class="col-md-4 col-form-label text-md-right">Jenis Motor</label>
                <div class="col-md-6">
                    <select class="form-control" name="motorcycle_brand_id">
                        <option value="" selected>Choose the motor version</option>
                        @foreach ($motorcycle_brands as $motor)
                            <option value="{{$motor->id}}" wire:key="motorcycle_brand{{$motor->id}}">{{$motor->motorcycle_brand_name}}</option>
                        @endforeach
                    </select>
                </div>
            </div>
        @endif
        <br>
        <!--End for the dynamic dropdown-->

        <div class="form-group">
            <label>Tahun Kendaraan</label>
            <input type="text" required class="form-control @error('kredit_vehicle') is-invalid @enderror" id="kredit_vehicle" name="kredit_vehicle" class="form-control" autocomplete="off" value="{{old('kredit_vehicle')}}" placeholder="Contoh : 2005" wire:model="kredit_vehicle">
        </div>
        @error('kredit_vehicle') 
            <div class="alert alert-danger">{{ $message }}</div>
        @enderror
        <br>
        <div class="form-group">
            <label>Rencana Pinjaman</label>
            <input type="text" required class="form-control @error('kredit_plan') is-invalid @enderror" id="kredit_plan" name="kredit_plan" class="form-control" autocomplete="off" value="{{old('kredit_plan')}}" placeholder="Contoh : 2,000,000" wire:model="kredit_plan">
        </div>
        @error('kredit_plan') 
            <div class="alert alert-danger">{{ $message }}</div>
        @enderror
        <br>
        <div class="form-group">
            <label>Keterangan</label><br>
            <textarea name="kredit_desc" id="kredit_desc" cols="79" rows="1" autocomplete="off" placeholder="Contoh : Motor Revo" wire:model="kredit_desc">{{old('kredit_desc')}}</textarea>
        <!--    <input type="text" id="kredit_vehicle" name="kredit_vehicle" class="form-control" placeholder="Contoh : Honda">-->
        </div>
        @endif

        <div class="action-buttons d-flex justify-content-between bg-white pt-2 pb-2">

            @if ($currentStep == 1)
                <div></div>
            @endif

            @if ($currentStep == 2)
                <button type="button" class="btn btn-info btn_secondary" id="btn_secondary" 
                style="background-color: #ffc107; border:none; color:black" wire:click="decreaseStep()">Previous</button>
            @endif

            @if ($currentStep == 1)
                <button type="button" class="btn btn-info btn_next" id="btn_next" 
                style="background-color: #ffc107; border:none; color:black" wire:click="increaseStep()">Next</button>                
            @endif

            @if ($currentStep == 2)
                <button type="submit" class="btn btn-info" id="btn_submit" 
                style="background-color: #ffc107; border:none; color:black">Ajukan Kredit</button>                
            @endif

        </div>
        
    </form>
</div>
<script src="https://cdn.jsdelivr.net/npm/[email protected]/dist/jquery.min.js"></script>
    <script>
        $(document).ready(function() {
            $(".is-invalid").first().focus();
        });
    </script>
0 likes
14 replies
Nicho's avatar
Level 1

@sr57 On this foreach??

<div class="form-group row">
            <label for="motorcycle" class="col-md-4">Merek motor</label>
            <div class="col-md-6">
                <select wire:model="brand_id" class="form-control">
                    <option value="" selected>Choose Motor</option>
                    @foreach ($motorcycles as $m)
                        <option value="{{$m->id}}">{{$m->motorcycle_name}}</option>
                    @endforeach
                </select>
            </div>
        </div>

Or both of the foreach??

Nicho's avatar
Level 1

@sr57 Is it like this??

<select wire:model="brand_id" class="form-control" wire:key="$loop->index">
                    <option value="" selected>Choose Motor</option>
                    @foreach ($motorcycles as $m)
                        <option value="{{$m->id}}">{{$m->motorcycle_name}}</option>
                    @endforeach
                </select>
sr57's avatar

Seem you didn't understand what I wrote

You have to add a key in your loop elt

and what about using a loop-index outside the loop?

Put wire:key="$loop->index" inside your loop ...

Snapey's avatar

You have multiple root elements in your view - a div and a script.

There can be only one root element. Put the script inside the div.

But why are you trying to use jquery inside the livewire component?

Nicho's avatar
Level 1

@Snapey It's for the error message, when the user put an invalid input on a certain form, it redirect it back to that field

Example : ID (max length 3): 1234 Name : ABC

It's invalid on the ID because max length only 3

So it will redirect to that invalid input

Nicho's avatar
Level 1

@Snapey Thank you for the advice, but i'm sorry, it still doesn fix the main issue that i'm having currently, the multiple root elements is gone.

But the main problem is when i click the submit button, it won't store the value that already filled

Nicho's avatar
Level 1

@Snapey Yeah, because when i do inspection there's a warning that said multiple root elements and i think that the source of the error, but it turns out wasn't. Forgive me sir, it's my bad

Snapey's avatar

you are adding the wire key wrong

<select wire:model="brand_id" class="form-control" wire:key="{{ $loop->index}}">
                    <option value="" selected>Choose Motor</option>
                    @foreach ($motorcycles as $m)
                        <option value="{{$m->id}}">{{$m->motorcycle_name}}</option>
                    @endforeach
                </select>

but that's not your problem and it won't fix anything

what is your problem?

Nicho's avatar
Level 1

@Snapey My problem is when data is filled, and when i try to click the submit button, it won't store the data/value that's already been filled into the database, it just stuck on that page

Snapey's avatar

@Nicho on step 1 or step 2?

does it call the competent method when you save?

you are going to have to narrow it down with some debugging

Nicho's avatar
Level 1

@Snapey It's on the step 2. As for the competent method, the , it has a function until you save the input

 public function createkredit(){
        if($this->currentStep == 2){
            $this->validate([
                'produk_id'=>'required',
                'motorcycle_id'=>'required',
                'motorcycle_brand_id'=>'required',
                'kredit_vehicle'=>'required',
                'kredit_plan'=>'required|numeric',
                'kredit_desc'=>'nullable'
            ]);
        }

        $values = array(
            "biaya_id" => $this->biaya_id,
            "produk_id"=> $this->produk_id,
            "promo_id"=> $this->promo_id,
            "motorcycle_id"=> $this->motorcycle_id,
            "motorcycle_brand_id"=>$this->motorcycle_brand_id,
            "domisili_id"=> $this->domisili_id,
            "kredit_nik"=> $this->kredit_nik,
            "kredit_name"=> $this->kredit_name,
            "kredit_phone"=> $this->kredit_phone,
            "kredit_phone2"=> $this->kredit_phone2,
            "kredit_vehicle"=> $this->kredit_vehicle,
            "kredit_plan"=> $this->kredit_plan,
            "kredit_desc"=> $this->kredit_desc,
            "brand_id"=> $this->brand_id
        );

        Kredit::insert($values);
        $this->reset();
        $this->currentStep = 1;

        return redirect()->to('/kredit');
    }

Please or to participate in this conversation.