Search code examples
phplaravellaravel-livewire

how do I do two way data binding on for each loop columns in laravel?


I have a foreach loop in a table that consist of multiple rows like this:

<td class="p-3 px-5">
    <input type="text"
        wire:model="email"
        value="{{$row->email}}"
        class="bg-transparent" >
</td>

Which gets data from:

$data = Teamuser::join('teams', 'teams.id', '=', 'team_user.team_id')
    ->join('users', 'users.id', '=', 'team_user.user_id')
    ->get([
        'users.name as username',
        'teams.name',
        'users.email',
        'team_user.role',
        'team_user.id',
        'team_user.user_id'
    ]);

return view('livewire.editusers',compact('data'));

I'm trying to use wire:model into a button to update data, the value doesnt works anymore. I need to do a two way data binding with something like this to insert data in my foreach's column.

public function edit($id)
{
    $user = Teamuser::findOrFail($id);
    $real = User::findOrFail($user_id);
    $third = Team::findOrFail($team_id);
    $this->username = $real->name;
    $this->email = $real->email;
    $this->team = $third->name;
    $this->role = $user->role;
}

but since there are multiple $id in foreach table, how do I insert all the datas in the for each column?

The view is something like this

@foreach($data as $row)
  @php 
    App\Http\Livewire\Teamusers::edit($row->id,$row->user_id,$row-team_id);
  @endphp

{{--call edit() function from teamusers component--}}


  <td class="p-3 px-5">
    <input type="text" wire:model="username" class="bg-transparent">
  </td>
  <td class="p-3 px-5">
    <input type="text" wire:model="email" value="{{$row->email}}" class="bg-transparent" >
  </td>
@endforeach

Edit:

I solved the binding problem by importing multiple models, but now it works like this.

enter image description here

I think its because the php code in the for each loop. But where else could i place it aside from there?


Solution

  • You're binding to your data incorrectly, you need to bind to a specific iteration within your $data.

    I don't have your database or dataset, so I have replicated a simplified example below using the default User model.

    Livewire Component

    <?php
    
    namespace App\Http\Livewire;
    
    use App\Models\User;
    use Livewire\Component;
    
    class ModelIterator extends Component
    {
        public $users;
    
        protected $rules = [
            'users.*.email' => ['required']
        ];
    
        public function mount()
        {
            $this->users = User::all();
        }
    
        public function render()
        {
            return view('livewire.model-iterator');
        }
    
        public function save($id)
        {
            $user = $this->users->where('id', $id)->firstOrFail();
    
            $user->save();
        }
    }
    

    Livewire Component View

    <div>
        @foreach ($users as $index => $user)
            <div wire:key="user-field-{{ $user->id }}">
                // Note the difference in how wire:model is defined here
                <input type="text" wire:model="users.{{ $index }}.email" />
                <button type="button" wire:click="save({{ $user->id }})">Save</button>
            </div>
        @endforeach
    </div>