Home > Software engineering >  How to use livewire pagination with public properties?
How to use livewire pagination with public properties?

Time:11-07

I'm facing a weird problem that only accurs when I use pagination with livewire components,

this is the error:

BadMethodCallException
Method Illuminate\Support\Collection::items does not exist.

I know what this errors means, the problem is why it only accurs when I change page in pagination:

this is my Component:

<?php

namespace App\Http\Livewire\Admin;

use Livewire\Component;
use Livewire\WithPagination;
use Livewire\WithFileUploads;
use App\Models\Product;
use App\Models\Category;
use File;
use GlobalsHelper;

class Products extends Component
{
    use WithPagination, WithFileUploads;

    public $products;
    public $subcategories;
    
    // Form
    public $name;
    public $description;
    public $price;
    public $quantity;
    public $category_id = null;
    public $sub_category_id = null;
    public $image;

    public $selected = [];
    public $query = '';
    public $filter_by_category = '';

    protected $paginationTheme = 'bootstrap';

    public function render()
    {
        $pagination = $this->products;
        $this->products = collect($this->products->items());

        return view('livewire.admin.products', [
            'categories' => Category::all(),
            'subcategories' => $this->subcategories,
            'products' => $this->products,
            'pagination' => $pagination
        ]);
    }
    // public function render()
    // {
    //     return view('livewire.admin.products', [
    //         'categories' => Category::all(),
    //         'subcategories' => $this->subcategories,
    //         'products' => $this->products,
    //     ]);
    // }

    public function mount()
    {
        $this->getSubcategories();
        $this->index();
    }

    public function getSubcategories()
    {
        $this->subcategories = [];
        if ( !$this->category_id )
        {
            $this->category_id = (Category::first()) ? Category::first()->id : null;
        }  

        $category = Category::find($this->category_id);
        if ( !$category )
        {
            return null;
        }
            
        $this->subcategories = $category->children;
        $this->sub_category_id = ($this->subcategories->first()) ? $this->subcategories->first()->id : null;
    }

    public function store()
    {
        $fields = $this->validate([
            'name' => ['required', 'string', 'min:5', 'max:250'],
            'description' => ['string', 'max:250'],
            'price' => ['required', 'numeric', 'min:1'],
            'quantity' => ['required', 'numeric', 'min:1'],
            'category_id' => ['nullable'],
            'sub_category_id' => ['nullable'],
        ]);

        $fields['user_id'] = GlobalsHelper::auth()->id;
        
        $product = Product::create($fields);
    
        if ( !$product )
        {
            session()->flash('error', __('messages.error_create'));
            return;
        }

        // upload image 
        $this->storeImage($product);

        $this->resetFields();

        session()->flash('success', __('messages.success_create'));
    }

    public function search()
    {
       $results = Product::where('name', 'LIKE', '%'.$this->query.'%')
                    ->orderBy('id', 'desc')->paginate(5);

       $this->products = $results;
    }

    public function index()
    {
        $this->products = Product::orderBy('id', 'desc')->paginate(5);
    }

    public function filterByCategory()
    {
       $results = Product::where('category_id', '=', $this->filter_by_category)
                    ->orderBy('id', 'desc')->paginate(5);

        
       $this->products = $results;
    }

    // private
    private function resetFields()
    {
        $this->name = null;
        $this->description = null;
        $this->price = 0;
        $this->quantity = 1;
        $this->image = null;
        $this->filename = '...';
    }

    private function storeImage($product)
    {
        $this->validate([
            'image' => ['nullable', 'image', 'max:1024'],
        ]);
        if ( $this->image )
        {
            // Delete old image if exists
            if ( $product->image )
            {
                File::delete([$product->image->fullpath]);
            }     
            $filename = sha1( uniqid('', true) );
            $ext = $this->image->getClientOriginalExtension();
            $fullpath = $this->image->store(GlobalsHelper::PRODUCTS_UPLOADS_DIR.'/'.$product->id, 'public');

            $product->update([
                'image' => [
                    'name' => basename($fullpath),
                    'type' => $ext,
                    'fullpath' => GlobalsHelper::STORAGE_DIR.$fullpath,
                    'url' => asset(GlobalsHelper::STORAGE_DIR.$fullpath)
                ]
            ]);
        }
    }
}

The idea is that I want to achieve search, store, update, delete, filter operations in same compoenent like in laravel controller, I found solutions online, but only 50% of what I need to achieve.

I have been wasting a lot of time trying to figure this out.

If any one would help me, I will be much appreciated.

CodePudding user response:

At first glance without seeing the view, you are getting the $produts via the mount() method, this will only run ONCE when the livewire component is first rendered. From the docs:

mount() is only ever called when the component is first mounted and will not be called again even when the component is refreshed or rerendered.

  • Related