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.