Model Binding Doesn't Work

I can’t do the model binding inside custom method in livewire component cause the data return as a json

Code

Parent Component:

<?php

namespace App\Http\Livewire;

use App\Contact;
use Livewire\Component;

class Nesting extends Component
{
    public $contacts;

    public function mount()
    {
        $this->contacts = Contact::all();
    }

    public function removeContact(Contact $contact)
    {
        $contact->delete();
        return $this->contacts;
    }


    public function render()
    {
        return view('livewire.nesting');
    }
}

Child Component:


<?php

namespace App\Http\Livewire;

use App\Contact;
use Livewire\Component;

class NestingChild extends Component
{
    public $contact;

    public function mount(Contact $contact)
    {
        $this->contact = $contact;
    }

    public function render()
    {
        return view('livewire.nesting-child');
    }
}

view

Parent Component:


<div>
    @foreach($contacts as $contact)
        <div>
            @livewire('nesting-child', ['contact' => $contact], key($contact->id))
            <button wire:click="removeContact('{{$contact->id}}')">Remove Contact</button>
        </div>
    @endforeach
</div>

Child Component:

<div>
    {{$contact->name}}
</div>

Any Idea?

It’s because you’re passing your $contact->id within quotes. Just dump it straight in and it should work.

Change:

<button wire:click="removeContact('{{$contact->id}}')">Remove Contact</button>

To:

<button wire:click="removeContact({{$contact->id}})">Remove Contact</button>

nothing happen.
it’s the same

Is the contact not being deleted or is it not returning something that you’re anticipating? If you add dd($contact) to the top of your removeContact method, you should see that the model is being injected. Can you try that out?

i tried already every solution in my mind but nothing happened
it returns a Model instance

App\Contact {#1280 ▼
  #connection: null
  #table: null
  #primaryKey: "id"
  #keyType: "int"
  +incrementing: true
  #with: []
  #withCount: []
  #perPage: 15
  +exists: false
  +wasRecentlyCreated: false
  #attributes: []
  #original: []
  #changes: []
  #casts: []
  #classCastCache: []
  #dates: []
  #dateFormat: null
  #appends: []
  #dispatchesEvents: []
  #observables: []
  #relations: []
  #touches: []
  +timestamps: true
  #hidden: []
  #visible: []
  #fillable: []
  #guarded: array:1 [▼
    0 => "*"
  ]
}

Since it’s returning the model instance, we know that model binding is working.

I think what you want to do is remove return $this->contacts but I’m unsure what you’re trying to accomplish just by the code provided. What you might want to do if you’re refreshing your contact models is to refetch after removing the contact so that any time there’s a change in the contacts it’ll update the front end. Try this for your parent code:

use App\Contact;
use Livewire\Component;

class Nesting extends Component
{
    public $contacts;

    public function mount()
    {
        $this->contacts = Contact::all();
    }

    public function removeContact(Contact $contact)
    {
        $contact->delete();
        $this->contacts = Contact::all(); //re-fetch contact list
    }


    public function render()
    {
        return view('livewire.nesting');
    }
}

The Problem here is the removeContact is not binding an eloquent Instance, its return a Contact Model instance instead

and you are right about the return $this->contacts but the contact is not removed in the first place.

The way you’re calling removeContact() would result in direct injection of an the eloquent model, Contact if your goal is to delete the contact identified by the id you’re passing in, you can do a destroy on the model’s primary key instead:

    public function removeContact($contactId) //make sure you remove the model type
    {
        Contact::destroy($contactId);
        $this->contacts = Contact::all(); //re-fetch contact list
    }

I’m not sure why calling delete directly on your model wasn’t working.

Thank for your reply.
yes i did this already but The thing i didn’t understand is why can’t Bind the Contact Model here and fetch the collection from it?

The model is binding properly. You’re not able to fetch a collection from it because you’re directly binding to one model through model injection on your method.

public function method(Model $model) will always try to bind to the specific model you pass to it. I’m unsure why you’re trying to get a collection this way. If you just want a collection of the models, do a Model::all().

In blade file all content in main div so its working fine
thnks(Rajesh Rathod)

Not sure from the conversation whether you solved the issue, but my solution was to emit “remove” event to a parent (owner of contact). This way is much simpler and more logical, because contacts belongs to the owner and the owner suppose to refresh list of contacts.
I have my own way to render elements, but the logic is following:

        $actions[] = ['dd-item', 'title' => "Delete item", 'href' => "#", "icon" => 'fa fa-times',
        "onClick" => "confirm('Are you sure?') || event.stopImmediatePropagation()",
        'wire:click' => '$emitUp("deleteItem",' . $this->item_id . ')'];

Update:
deleteItem has to be declared as event