How to Pass a Collection to a view

I have sent a collection of arrays to my Livewire controller:
@livewire(‘deals’, $deals)

Then in my controller, I accept the collection and can dd($deals) and see all the data in the collection.

<?php namespace App\Http\Livewire; use Livewire\Component; class Deals extends Component { public $deals; public function mount($deals) { //dd($deals); return view('livewire.tasks', [ 'deals' => $deals, ]); } } But I can't get it into the view. I get an error on the first line: @foreach($deals as $deal) Error: Undefined variable: deals What am I doing wrong? Thanks!

Do you have a render method? Did you try something like below?

<?php 
namespace App\Http\Livewire; 
use Livewire\Component; 

class Deals extends Component { 

    public $deals; 

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

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

I receive this error:

Livewire component’s [deals] public property [deals] must be of type: [numeric, string, array, null, or boolean]. Only protected or private properties can be set as other types because JavaScript doesn’t need to access them.

I believe it is because $deals is technically a Collection, and not an Array, but if I use toArray() to change the collection to an array, I lose the naming, like “$deals”, right?

In the current version of Livewire, public properties need to be data structures that work in JS too. This means you need to store your collection in another way, or store an array of deal ids that you re-hydrate in the render function.

This issue gives more context: https://github.com/livewire/livewire/issues/488

Thanks for the clarification.

I was in such a hurry to start using Livewire, that I assumed that it used all the parts of Laravel in the same way. I’m learning that since this is JS focused, the needs of JS take precedence. So we can’t send Collections to Livewire, we have to send arrays. I am converting my existing view to a Livewire component and am running into issues one at a time and learning through the process.

I really wish that Livewire could deal with collections, relationships, and member functions at some point so we don’t have to convert so much code.

Even to the point that I am used to adding a simple

->sortByDesc('created_at')

or

->diffForHumans()

to a field within a @foreach loop, but I can’t do that, because it’s an array now, which removes a lot of the beauty and simplicity that I have come to love about Laravel.

What would it take for Livewire to be able to use these member functions in the Livewire views?

So…you can still use models and collections. One way is to accept a collection in mount, pluck the ids, and store those in a public property. Then, in render you can fetch the collection again, and pass that to the component’s view.

Looks like Livewire is gonna start handling models and collections in public properties, at least.

That would be great. Currently, I am using

->toArray()

to convert all my collections to arrays and using

$this->variable = $variable->toArray();

for my data.

Which also means I have to change all of my

$variable->value

to

$this->variable['value']

which is really taking a big step backwards from a Laravel standpoint, and a BUNCH of editing to an existing view that used to work just fine until I wanted to add Livewire functionality.

Something like this should do the trick: https://gist.github.com/assertchris/4ac3d01a5e20eb4dce7e5c6afce3c6d1

1 Like

Whenever I go the collection route, I receive this type of error:

Livewire component’s [tasks] public property [deal] must be of type: [numeric, string, array, null, or boolean]. Only protected or private properties can be set as other types because JavaScript doesn’t need to access them.

But I’ll try what you sent me. Though I just made all the edits to make the arrays work. :slight_smile:

In my example, I forgot to get an array out of the collection of plucked ids. $deals->pluck('id')->all().

So technically you can work with collections to a point but they then have to become arrays for Livewire to work with the data?

Also, I don’t see the need for render() and mount().

Laravel doesn’t do this. You receive data into the function within a controller, and manipulate that data, then call a view.

The whole concept of public variables, then using $this-> just to pass the variable data again, creating the need to put $this-> all over your view is something most people don’t do in Laravel any more.

Livewire is technically a component and not a view standing on its own, but it could just be functionality that works with all of Laravel’s existing code structure. I understand that I am a bit of a novice dealing with a pre-1.0 piece of software, but I am still learning.

With the latest release a few hours ago, you should now be able to set a public property to a model or collection. Upgrade and give it a shot. :+1:

1 Like