laravel-livewirealpine.jslaravel-10laravel-livewire-wiremodel

Binding Livewire nested data insertion using Alpine js


In screenshot below i have a set of data insertion which contains each parent might have o to 6 children : livewire form which is using alpine js for biding nested data insertion fields

when i try to get data in my livewire blade (the part facing issue) like below:

    <div class="form-group mb-4"  x-data="{ count: @entangle('childrenCount')}">
    <label> number of childs</label>
     <input type="number" min="0" max="6"   wire:model.number="tedad" x-model.number="count" />

    <template x-for="(child,i) in count" :key="i" class="p-2">
     <div class="child-fields  p-2">

           <input type="text" placeholder="ﻥﺎﻣ ﻭ ﻥﺎﻣ ﺥﺎﻧﻭﺍﺪﮕﯾ " class="btn form-control form-control-sm" x-model="child.name"  wire:model.defer="children[i].name"/><br>
        <input type="text" placeholder="ﺶﻣﺍﺮﻫ ﺶﻧﺎﺴﻧﺎﻤﻫ" class="btn form-control form-control-sm"   x-model="child.shenasnameChild"  wire:model.defer="children[i].shenasnameChild" /><br>
        <input type="text" placeholder="ﮎﺩ ﻢﻠﯾ" class="btn form-control form-control-sm" x-model="child.codemeliChild"  wire:model.defer="children[i].codemeliChild" />
        <input type="text" placeholder="ﮎﺩ ﻢﻠﯾ ﺐﯿﻤﻫ ﺵﺪﻫ ﺎﺼﻠﯾ" class="btn form-control form-control-sm" x-model="child.codemeliasli"  wire:model.defer="children[i].codemeliasli" />
      <input type="text" placeholder="ﺕﺍﺮﯿﺧ ﺕﻮﻟﺩ" class="btn form-control form-control-sm" x-model="child.tavalodChild"  wire:model.defer="children[i].tavalodChild" />
      <input type="text" placeholder="ﻥﺎﻣ ﭖﺩﺭ" class="btn form-control form-control-sm" x-model="child.pedarChild"  wire:model.defer="children[i].pedarChild" />
     <input type="text" placeholder="ﻦﺴﺒﺗ" class="btn form-control form-control-sm"  x-    model="child.nesbat"   wire:model.defer="children[i].nesbat" />


    </div>

  </template>
</div>    

it seems , the fields data did not sent to the livewire component properly and shows me empty set in database. here is my livewire component:

1.my updatedChildrenCount for handling number of children entered by client:

   public function updatedChildrenCount($value)
    {
    $this->childrenCount = (int) $value;
    $this->children = array_slice($this->children ?? [], 0, $this->childrenCount);
    for ($i = 0; $i < $this->childrenCount; $i++) {
        if (!isset($this->children[$i])) {
            $this->children[$i] = [
                'name' =>'',
                'shenasnameChild' => '',
                'codemeliChild' => '',
                'codemeliasli' => '',
                'tavalodChild' => '',
                'pedarChild' => '',
                'nesbat' => '',
            ];
        }
     }
  }

2- the submission function in the livewire component:

  public function submit()
     {

            $this->validate();
            $this->registeredNumber = strtoupper(Str::random(9));
    
       $Akmal= akmals::create([
             'fname' => $this->fname,
             'lname' => $this->lname,
             'codemeli' => $this->codemeli,
             'edare' => $this->edare,
             'tavalod'=>$this->tavalod,
              'sheba' => $this->sheba,
                'hesabnum' => $this->hesabnum,
                'nahieh' => $this->nahieh,
                'daftarekol'=> $this->daftarekol,
            'tedad' => $this->tedad,
              'codepersoneli' => $this->codepersoneli,
             'ostan'=> $this->ostan,
               'tel' => $this->tel,
               'shenasname' =>$this->shenasname,
               'pedar' => $this->pedar,
               'registered_number' => $this->registeredNumber,
        ]);

    if(!empty($this->childrenCount)){

           $childrenData=[];
            foreach($this->children as $child){
                    $childrenData[]=[
            'akmal_id'=>$Akmal->id,
            'name'=>$child['name']??null,
            'shenasnameChild'=>$child['shenasnameChild']?? null,
            'codemeliChild'=>$child['codemeliChild']??null,
            'codemeliasli'=>$child['codemeliasli']??null,
            'tavalodChild'=>$child['tavalodChild']??null,
            'pedarChild'=>$child['pedarChild']??null,
            'nesbat'=>$child['nesbat']??null,
            ];
                    
            }
   
             $Akmal->AkmalChild()->createMany($childrenData);
            }

Solution

  • You should let Livewire manage the state and the loop entirely. Alpine.js is not needed here and is preventing the data from being correctly bound to your Livewire component.
    Try using this approach below:

    
    <div class="form-group mb-4">
        <label>Number of Children</label>
        
        <input type="number" min="0" max="6" class="form-control" wire:model.live="childrenCount" />
    
        @foreach($children as $index => $child)
            <div class="child-fields p-2 border mt-2" wire:key="child-{{ $index }}">
    
                <input type="text" placeholder="ﻥﺎﻣ ﻭ ﻥﺎﻣ ﺥﺎﻧﻭﺍﺪﮕﯾ " class="form-control form-control-sm mb-2" wire:model.defer="children.{{ $index }}.name" />
                
                <input type="text" placeholder="ﺶﻣﺍﺮﻫ ﺶﻧﺎﺴﻧﺎﻤﻫ" class="form-control form-control-sm mb-2" wire:model.defer="children.{{ $index }}.shenasnameChild" />
                
                <input type="text" placeholder="ﮎﺩ ﻢﻠﯾ" class="form-control form-control-sm mb-2" wire:model.defer="children.{{ $index }}.codemeliChild" />
                
                <input type="text" placeholder="ﮎﺩ ﻢﻠﯾ ﺐﯿﻤﻫ ﺵﺪﻫ ﺎﺼﻠﯾ" class="form-control form-control-sm mb-2" wire:model.defer="children.{{ $index }}.codemeliasli" />
                
                <input type="text" placeholder="ﺕﺍﺮﯿﺧ ﺕﻮﻟﺩ" class="form-control form-control-sm mb-2" wire:model.defer="children.{{ $index }}.tavalodChild" />
                
                <input type="text" placeholder="ﻥﺎﻣ ﭖﺩﺭ" class="form-control form-control-sm mb-2" wire:model.defer="children.{{ $index }}.pedarChild" />
                
                <input type="text" placeholder="ﻦﺴﺒﺗ" class="form-control form-control-sm" wire:model.defer="children.{{ $index }}.nesbat" />
    
            </div>
        @endforeach
    </div>
    

    Then in your Livewire component class, make sure you have this public property:

    public $childrenCount = 0;
    public $children = [];
    

    Let me know if this helps