使用分页数据时Livewire引发错误



因此,当我试图对数据进行分页并通过livewire组件将其发送到视图时,会出现此错误。

我正在尝试获得所有的帖子,并在laravel中使用分页显示每页最多5个帖子。

Livewire版本:2.3.1
Laravel版本:8.13.0

错误:

LivewireExceptionsPublicPropertyTypeNotAllowedException
Livewire component's [user-posts] public property [posts] 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.

我的组件:

<?php
namespace AppHttpLivewire;
use LivewireComponent;
use AppModelsPost;
use LivewireWithPagination;
class UserPosts extends Component
{
use WithPagination;
public $posts;
public $type;
protected $listeners = ['refreshPosts'];

public function delete($postId)
{
$post = Post::find($postId);
$post->delete();
$this->posts = $this->posts->except($postId);
}
public function render()
{
if($this->type == 'all')
$this->posts = Post::latest()->paginate(5);
else if($this->type == 'user')
$this->posts = Post::where('user_id',Auth::id())->latest()->paginate(5);
return view('livewire.user-posts', ['posts' => $this->posts]);
}
}

我的刀片:

<div wire:poll.5s>
@foreach($posts as $post)
<div style="margin-top: 10px">
<div class="post">
<div class="flex justify-between my-2">
<div class="flex">
<h1>{{ $post->title }}</h1>
<p class="mx-3 py-1 text-xs text-gray-500 font-semibold"
style="margin: 17px 0 16px 40px">{{ $post->created_at->diffForHumans() }}</p>
</div>
@if(Auth::id() == $post->user_id)
<i class="fas fa-times text-red-200 hover:text-red-600 cursor-pointer"
wire:click="delete({{$post->id}})"></i>
@endif
</div>
<img src="{{ asset('image/banner.jpg') }}" style="height:200px;"/>
<p class="text-gray-800">{{ $post->text }}</p>
@livewire('user-comments', [
'post_id' => $post->id,
'type' => 'all'
],
key($post->id)
)
</div>
</div>
@endforeach
{{ $posts->links() }}
</div>

$posts不应声明为Livewire组件类中的属性,您使用laravelview((助手将posts作为数据传递

删除线路

public $posts;

并替换$this->在渲染功能中按$posts发布:

public function render()
{
if($this->type == 'all')
$posts = Post::latest()->paginate(5);
else if($this->type == 'user')
$posts = Post::where('user_id',Auth::id())->latest()->paginate(5);
return view('livewire.user-posts', ['posts' => $posts]);
}
}

供我参考,以及遇到这个问题的人。

有时,您需要将querypagination添加到mount中,或者可能在某些function中添加id

这是你必须做的两个选项。

  1. 在底座中

如错误所示

Livewire组件的公共属性的类型必须为:[数字,….只能设置受保护的或私有的属性

因此,在这种情况下,可以将属性定义为protected而不是public,并在渲染中调用它。

快速示例。

protected $posts;
public function mount()
{
$this->posts = Post::paginate(15);
}
public function render()
{
return view('livewire.view',[
'posts'=>$this->posts
]);
}
  1. 在某些函数中

为什么要使用computed properties更优雅

快速示例。

use WithPagination;
public $postId;

public function getPostsProperty(): LengthAwarePaginator
{
return Post::find($this->postId)->comments()->paginate(10);
}
public function render(): Factory|View|Application
{
return view('livewire.view');
}

现在,在本例中,$this->posts可以从组件的类或Blade视图访问。从这里阅读更多

这里有更多来自GitHub问题的参考

这是我解决这个问题的方法。基本上,我不会将paginate设置为livewire组件属性。相反,我有用于筛选和排序的属性。然后在渲染之前,我运行查询来获取数据。在这个产品列表组件中,我按类别筛选以获得产品,并按标题、价格或created_at对其进行排序。

这是我的火线ProductList组件:

<?php
namespace AppLivewire;
use AppModelsProduct;
use AppModelsProductCategory;
use IlluminateContractsViewFactory;
use IlluminateContractsViewView;
use LivewireAttributesComputed;
use LivewireComponent;
use LivewireWithPagination;
class ProductList extends Component
{
use WithPagination;
public $categoryId = 1;
public $sort = 'latest';
public $sortColumn = 'created_at';
public $sortOrder = 'desc';
#[Computed]
public function categories()
{
return ProductCategory::select('id', 'name')->get();
}
public function render(): View|Factory
{
return view(
'livewire.product-list',
[
'products' => Product::select('id', 'title', 'price', 'thumbnail', 'slug')
->where('category_id', $this->categoryId)
->orderBy($this->sortColumn, $this->sortOrder)
->paginate(15),
]
);
}
public function updateSort()
{
switch ($this->sort) {
case 'title_asc':
$this->sortColumn = 'title';
$this->sortOrder = 'asc';
break;
case 'title_desc':
$this->sortColumn = 'title';
$this->sortOrder = 'desc';
break;
case 'price_asc':
$this->sortColumn = 'price';
$this->sortOrder = 'asc';
break;
case 'price_desc':
$this->sortColumn = 'price';
$this->sortOrder = 'desc';
break;
default:
$this->sortColumn = 'created_at';
$this->sortOrder = 'desc';
}
}
}

这是我的看法product-list.blade.php:

@pushOnce('styles')
@vite(['resources/scss/components/product-list.scss'])
@endPushOnce
<div>
<div class="flex flex-col space-y-8 md:space-y-0 md:flex-row justify-between">
<select name="categories" class='product-filter' wire:change="updateSort" wire:model="categoryId">
@foreach($this->categories as $category)
<option class="category-item" value="{{ $category->id }}" wire:key={{ $category->id }}>{{ $category->name }}</option>
@endforeach
</select>
<select name="sort" class='product-filter' wire:change="updateSort" wire:model="sort">
@foreach(['latest' => 'latest', 'title_asc' => 'title (a->z)', 'title_desc' => 'title (z->a)', 'price_asc' => 'price: low to high', 'price_desc' => 'price: high to low'] as $sortKey=>$sortItem)
<option class="sort-item" value="{{ $sortKey }}" wire:key={{ $sortKey }}>{{ $sortItem }}</option>
@endforeach
</select>
</div>
<div class="product-container animate__animated">
@foreach ($products as $productIndex => $product)
<div class="product-card" wire:key={{ $product->id }}>
<p class="product-title">{{ $product->title }}</p>
<p class="product-price">$ {{ $product->price }} USD</p>
<img class="product-image" src="{{ $product->thumbnail }}" alt="Product Thumbnail" />
<x-button content="View details" type="secondary" link="{{ 'products/' . $product->slug }}"></x-button>
</div>
@endforeach
</div>
<div class="pagination">
{{ $products->links() }}
</div>
</div>

希望得到帮助。

最新更新