livewire: Livewire component's public property 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.

public function render()
    {
        return view('livewire.user', ['contacts'=>\App\User::paginate(5)]);
    }

This worked well. But when I did as following, it showed error such as title.

public $contacts;

public function mount()
{
    $this->contacts = \App\User::paginate(5);
}
public function render()
{
     return view('livewire.user');
}

About this issue

  • Original URL
  • State: closed
  • Created 4 years ago
  • Comments: 32

Most upvoted comments

I was banging my head so long on this issue. Found the solution.

As it says in the error the properties in a livewire component can be only [numeric, string, array, null, boolean] types

so if we want a different type to be passed (a collection for example) we will need to make it a protected/private property

    protected $items;

    public function mount()
    {
        $this->items = Product::paginate(20);
    }

    public function render()
    {
        return view('livewire.datatable',[
            'items'=>$this->items
        ]);
    }

I faced the same problem, but what I’ve done is:

$items_tpl = MyModel::Paginate(5);
$this->items = collect($items_tpl->items());
return view('livewire.index', ['items_tpl' => $items_tpl]);

and kept iterating over $items in the component, but took the pagination like that $items_tpl->links()

I did the following:

product

products

At least it worked for me

Yeah, I ran into this yesterday. The problem is that ::paginate() returns a “LengthAwarePaginator” instead of an “EloquentCollection”, so Livewire doesn’t know how to dehydrate it.

As a work around, you could convert the length aware paginator to an Eloquent Collection before setting as a property.

I will try to follow up with an example when I’m at my computer.

Appreciate an example to “convert the length aware paginator to an Eloquent Collection” or a reference.

Another way, more elegant in my opinion, is to use computed properties. It can return other types than those accepted by LiveWire in public properties.

Quick example :


   use WithPagination;

    public $sortOrder = 'asc';
    public $sortTerm = 'name';

    public function sortByName(): void
    {
        $this->sortTerm = 'name';
        $this->sortOrder = $this->sortOrder === 'asc' ? 'desc' : 'asc';
    }

    public function getContactsProperty(): LengthAwarePaginator
    {
        return Contact::query()
            ->orderBy($this->sortTerm, $this->sortOrder)
            ->paginate(20);
    }

    public function render(): Factory|View|Application
    {
        return view('livewire.contacts-data-table');
    }

Also facing this issue.

I would like to pass the paged data from the controller. Is this not possible? I mean, the livewire components are going to replace the logic in the controllers? I would like to keep my logic in the controllers and livewire for rendering only.

Running into this as well, would love to figure out how to solve it.

The question itself has the answer and the OP mentioned it. Just move the pagination to the render method as follow

<?php

namespace App\Http\Livewire\Blog;

use Livewire\Component;
use Livewire\WithPagination;
use App\Models\Blog as ModelsBlog;

class Blog extends Component
{
    use WithPagination;

    // public $blogs;

    // public function mount()
    // {
    //     $this->blogs = ModelsBlog::paginate(10);
    // }

    public function render()
    {
        return view('livewire.blog.blog', [
            'blogs' => ModelsBlog::paginate(10)
        ]);
    }
}

Using use WithPagination; is optional. (Added my comment so that this could help future users who comes from Google search)

I have done the below.

use Livewire\WithPagination;

class Posts extends Component
{

public $posts;
use WithPagination;
 protected $paginationTheme = 'bootstrap';

public function render()
    {
        $this->posts = Post::paginate(5)->all();
        return view('livewire.posts',[
            'pagination' => Post::paginate(5),
    ]);
}
@foreach ($posts as $post)
<tr>
      <td>{{ $post->id }}</td>
      <td>{{ $post->title }}</td>
      <td>{{ $post->body }}</td>
      <td>
        <button wire:click="edit({{ $post->id }})" class="btn btn-primary btn-sm">Edit</button>
        <button wire:click="delete({{ $post->id }})" class="btn btn-danger btn-sm">Delete</button>
      </td>
</tr> 
@endforeach

  {!! $pagination->render() !!}

it works for me.

public function render()
    {
        return view('livewire.user', ['contacts'=>\App\User::paginate(5)]);
    }

This worked well. But when I did as following, it showed error such as title.

public $contacts;

public function mount()
{
    $this->contacts = \App\User::paginate(5);
}
public function render()
{
     return view('livewire.user');
}

Make the $contacts as protected and pass the value in render method. The final code is as follows

protected $contacts;

public function mount()
{
    $this->contacts = \App\User::paginate(5);
}
public function render()
{
     return view('livewire.user', ['contacts' => $this->contacts]);
}

in my case it worked

I did the following:

product

products

At least it worked for me

Thanks friend, it helped me, only that I have to order the columns and when I click it tells me: BadMethodCallException Method Illuminate \ Support \ Collection :: items does not exist. any solution for this, maybe you already fixed it?

The question itself has the answer and the OP mentioned it. Just move the pagination to the render method as follow

<?php

namespace App\Http\Livewire\Blog;

use Livewire\Component;
use Livewire\WithPagination;
use App\Models\Blog as ModelsBlog;

class Blog extends Component
{
    use WithPagination;

    // public $blogs;

    // public function mount()
    // {
    //     $this->blogs = ModelsBlog::paginate(10);
    // }

    public function render()
    {
        return view('livewire.blog.blog', [
            'blogs' => ModelsBlog::paginate(10)
        ]);
    }
}

Using use WithPagination; is optional. (Added my comment so that this could help future users who comes from Google search)

It worked for me but you can’t have public … on your livewire controller otherwise didnt work for me.

Also, set up new livewire pagination with ‘php artisan livewire:publish --pagination’

and do: {{ $blogs->links(‘vendor.livewire.bootstrap’) }} on your view