如何使用 laravel livewire 和分页修复奇怪的行为?
How to fix a strange behaviour with laravel livewire and pagination?
几天前我开始使用Laravel 8和livewire。我还有很多东西要发现,但我正在路上。
最后,我遇到了一个我难以理解的行为。
我的目标
我想为 CRUD post 创建一个页面。我想要的是在页面底部显示一个分页显示的 post 列表,一个创建新 post 的按钮以及单击每个 post 行上的按钮的可能性编辑 post。
我还希望 post 的编辑器在列表隐藏时显示在页面顶部(但这最后一种可能性并不是绝对必要的)。
只要 post 列表没有分页但没有分页,我就可以让它工作。
为此,我使用了一个 liveewire 组件,其代码如下:
app/Http/livewire/posts/Posts.php
中的组件代码
<?php
namespace App\Http\Livewire\Posts;
use App\Models\Post;
use Livewire\Component;
class Posts extends Component
{
public $posts;
public $links;
public $post_id,$title, $abstract, $body,$category,$diaporama_dir,
$beg_date,$end_date,$close_date,$receive_registration,
$sticky,$user_id,$inscription_directive;
/**
* The attributes that are mass assignable.
*
* @var array
*/
public function render()
{
$this->mode='list';
$this->posts=Post::select('id','title')->orderBy('created_at','DESC')->paginate(15)->toArray();
$this->links=$this->posts['links'];
//dd($this->links);
$this->user_id=auth()->user()->id;
return view('livewire.posts.posts');
}
public function donothing(){
}
/*
* The attributes that are mass assignable.
*
* @var array
*/
public function resetInputFields(){
$this->title = '';
$this->body = '';
$this->title='';
$this->abstract='';
$this->body='';
$this->category='';
$this->diaporama_dir='';
$this->beg_date='';
$this->end_date='';
$this->close_date='';
$this->receive_registration='';
$this->sticky='';
$this->inscription_directive='';
}
/**
* The attributes that are mass assignable.
*
* @var array
*/
public function store()
{
$validatedData = $this->validate([
'title' => 'required',
'body' => 'required',
'abstract'=>'required',
'category'=>'',
'diaporama_dir'=>'',
'beg_date'=>'sometimes',
'end_date'=>'sometimes',
'close_date'=>'sometimes',
'receive_registration'=>'',
'sticky'=>'',
'user_id'=>'required',
'inscription_directive'=>''
]);
Post::create($validatedData);
session()->flash('message', 'Bravo ! Votre article a été enregistré.');
// $this->resetInputFields(); //user may want to keep the input stable
}
/**
* The attributes that are mass assignable.
*
* @var array
*/
public function edit($id)
{
$post = Post::findOrFail($id);
$this->post_id = $id;
$this->title = $post->title;
$this->abstract=$post->abstract;
$this->body=$post->body;
$this->category=$post->category;
$this->diaporama_dir=$post->diaporama_dir;
$this->beg_date=$post->beg_date;
$this->end_date=$post->end_date;
$this->close_date=$post->close_date;
$this->receive_registration=$post->receive_registration;
$this->sticky=$post->sticky;
$this->inscription_directive=$post->inscription_directive;
$this->dispatchBrowserEvent('notify','je passe en mode edit');//to switch browser page to edit mode
}
/**
* The attributes that are mass assignable.
*
* @var array
*/
public function update()
{
$validatedData = $this->validate([
'title' => 'required',
'body' => 'required',
'abstract'=>'required',
'category'=>'',
'diaporama_dir'=>'',
'beg_date'=>'sometimes',
'end_date'=>'sometimes',
'close_date'=>'sometimes',
'receive_registration'=>'',
'sticky'=>'',
'user_id'=>'required',
'inscription_directive'=>''
]);
$post = Post::find($this->post_id);
$post->update([
'title' => $this->title,
'body'=> $this->body,
'abstract'=> $this->abstract,
'category'=> $this->category,
'diaporama_dir'=>$this->diaporama_dir,
'beg_date'=>$this->beg_date,
'end_date'=>$this->end_date,
'close_date'=>$this->close_date,
'receive_registration'=>$this->receive_registration,
'sticky'=>$this->sticky,
'user_id'=>$this->user_id,
'inscription_directive'=>$this->inscription_directive
]);
session()->flash('message', "Bravo ! L'article a été mis à jour.");
// $this->resetInputFields();//user may like to keep the input fields stable
}
}
观点如下:
视图 1:resources/views/livewire/posts/posts 中的主页。blade.php
<div class="container m-auto w-10/12">
<div x-data="{ mode: 'list' }">
@if (session()->has('message'))
<div class="bg-green-200 p-4 w-full my-8 text-xl text-orange-500">
{{ session('message') }}
</div>
@endif
<div x-on:notify.window="mode = 'update'">
<div x-show="mode==='update'">
@include('livewire.posts.update')
</div>
<div x-show="mode === 'edit'">
@include('livewire.posts.create')
</div>
</div>
{{-- <div x-show="mode === 'list'" class="">--}}
<div>
<div>
<button x-on:click="mode = 'edit'" class="bg-red-400 px-2 py-1 border rounded-lg mt-2">Nouvel
article</button>
</div>
<table class=" bg-green-400 w-full table table-bordered mt-5 ">
<thead>
<tr class="bg-red-50 mb-2">
<th>Id.</th>
<th>Titre</th>
<th width="150px">Action</th>
</tr>
</thead>
<tbody>
@for ($i = 0; $i < $posts['per_page']; $i++)
<tr class="bg-red-400 mb-2 p-2 space-y-2 border-8 border-red-50 ">
<td>{{ $posts['data'][$i]['id'] }}</td>
<td>{{ $posts['data'][$i]['title'] }}</td>
<td>{{--les actions--}}
<button wire:click="edit({{ $posts['data'][$i]['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>
@endfor
</tbody>
</table>
<div class="flex flex-row mt-2">
@for ($i = 0; $i < count($links); $i++)
<div class="flex p-2 mr-2 border w-max-content">
<a href="{{$links[$i]['url'] }}">{{$links[$i]['label']}}</a>
</div>
@endfor
</div>
</div>
</div>
2- 创建包含在 resources/views/livewire/posts/create.blade.php
<div class="container bg-green-500 p-4">
<form>
This is the create form
<input type="hidden" name="user_id" wire:model="user_id" >
<div class="flex flex-col md:flex-row" >
<div class=" mt-2 flex flex-col w-max-content">
<label for="category">Catégorie:</label>
<select class="" name="category" id="category" wire:model="category">
<option value="Sans">Sans</option>
<option value="Annoncement">Annonce d'un événement</option>
</select>
@error('category') <span class="text-danger">{{ $message }}</span>@enderror
</div>
<div class=" mt-2 flex flex-col flex-auto ml-4">
<label for="title">Title:</label>
<input type="text" class="form-control" name="title" id="title" placeholder="Saisissez un titre"
wire:model="title" value="">
@error('title') <span class="text-danger">{{ $message }}</span>@enderror
</div>
</div>
<div class="flex flex-col md:flex-row" >
<div class=" mt-2 flex flex-col w-max-cbeg_date ">
<label for="beg_date">Date de début</label>
<input type="text" class="" name="beg_date" id="beg_date" wire:model="beg_date">
@error('beg_date') <span class="text-danger">{{ $message }}</span>@enderror
</div>
<div class=" mt-2 flex flex-col w-max-cbeg_date ml-4">
<label for="end_date">Datend_date</label>
<input type="text" class="" name="end_date" id="end_date" wire:model="end_date">
@error('end_date') <span class="text-danger">{{ $message }}</span>@enderror
</div>
<div class=" mt-2 flex flex-col w-max-cbeg_date ml-4">
<label for="close_dclose">Date limite</label>
<input type="text" class="" name="close_date" id="close_date" wire:model="close_date">
@error('close_date') <span class="text-danger">{{ $message }}</span>@enderror
</div>
<div class=" mt-2 flex flex-col w-max-content ml-4">
<label for="receive_registration">Accepte les inscriptions:</label>
<select class="" name="receive_registration" id="receive_registration" wire:model="receive_registration">
<option value="no">Non</option>
<option value="yes">Oui</option>
</select>
@error('receive_registration') <span class="text-danger">{{ $message }}</span>@enderror
</div>
<div class=" mt-2 flex flex-col flex-auto ml-4">
<label for="title">Dossier du diaporama</label>
<input type="text" class="form-control" name="diaporama_dir" id="diaporama_dir" placeholder="ex: admin/1"
wire:model="diaporama_dir">
@error('diaporama_dir') <span class="text-danger">{{ $message }}</span>@enderror
</div>
</div>
<div class="mt-2 flex flex-col">
<label for="abstract">Résumé</label>
<textarea class="form-control" name="abstract" id="abstract" wire:model="abstract"
placeholder="Saisissez votre article"></textarea>
@error('abstract') <span class="text-danger">{{ $message }}</span>@enderror
</div>
<div class="mt-2 flex flex-col">
<label for="body">Corps de l'article</label>
<textarea class="form-control" name="body" id="body" wire:model="body" rows=30
placeholder="Saisissez votre article"></textarea>
@error('body') <span class="text-danger">{{ $message }}</span>@enderror
</div>
<button wire:click.prevent="store()" class="bg-red-400 px-2 py-1 border rounded-lg mt-2">Enregistrer</button>
<button wire:click.prevent="resetInputFields()" class="bg-red-400 px-2 py-1 border rounded-lg mt-2">Effacer tout</button>
<button @click.prevent="mode = 'list'" class="bg-red-400 px-2 py-1 border rounded-lg mt-2 ml-16">Retour à la liste</button>
</form>
更新包括
除了 post id 的附加隐藏字段外,更新包含与创建包含完全相同。
发生了什么事?
在启动时,我的意思是当我访问 localhost:8000/posts 页面时,页面 1 正确显示并且 links在页面底部像 localhost:8000/posts?page=3 以页码为准。
从这个页面我通常可以使用底部 links 转到另一个页面,而且这几次。
点击link编辑post时出现问题。 post 由服务器正确发回,但我们立即 切换到分页 post 的第 1 页 和底部 link 奇怪的形式例如localhost:8000/livewire/message/posts.posts?page=3 无论页码是多少。
当我在显示创建表单后,在字段中键入第一个字符时,也会出现问题。事实上,它似乎每次需要同步时都会出现。
我该如何解决这个问题?
替换
<div class="flex flex-row mt-2">
@for ($i = 0; $i < count($links); $i++)
<div class="flex p-2 mr-2 border w-max-content">
<a href="{{$links[$i]['url'] }}">{{$links[$i]['label']}}</a>
</div>
@endfor
</div>
和
<div class="flex flex-row mt-2">
{{ $posts->links() }}
</div>
并在组件中
use WithPagination;
几天前我开始使用Laravel 8和livewire。我还有很多东西要发现,但我正在路上。
最后,我遇到了一个我难以理解的行为。
我的目标
我想为 CRUD post 创建一个页面。我想要的是在页面底部显示一个分页显示的 post 列表,一个创建新 post 的按钮以及单击每个 post 行上的按钮的可能性编辑 post。 我还希望 post 的编辑器在列表隐藏时显示在页面顶部(但这最后一种可能性并不是绝对必要的)。
只要 post 列表没有分页但没有分页,我就可以让它工作。
为此,我使用了一个 liveewire 组件,其代码如下:
app/Http/livewire/posts/Posts.php
中的组件代码<?php
namespace App\Http\Livewire\Posts;
use App\Models\Post;
use Livewire\Component;
class Posts extends Component
{
public $posts;
public $links;
public $post_id,$title, $abstract, $body,$category,$diaporama_dir,
$beg_date,$end_date,$close_date,$receive_registration,
$sticky,$user_id,$inscription_directive;
/**
* The attributes that are mass assignable.
*
* @var array
*/
public function render()
{
$this->mode='list';
$this->posts=Post::select('id','title')->orderBy('created_at','DESC')->paginate(15)->toArray();
$this->links=$this->posts['links'];
//dd($this->links);
$this->user_id=auth()->user()->id;
return view('livewire.posts.posts');
}
public function donothing(){
}
/*
* The attributes that are mass assignable.
*
* @var array
*/
public function resetInputFields(){
$this->title = '';
$this->body = '';
$this->title='';
$this->abstract='';
$this->body='';
$this->category='';
$this->diaporama_dir='';
$this->beg_date='';
$this->end_date='';
$this->close_date='';
$this->receive_registration='';
$this->sticky='';
$this->inscription_directive='';
}
/**
* The attributes that are mass assignable.
*
* @var array
*/
public function store()
{
$validatedData = $this->validate([
'title' => 'required',
'body' => 'required',
'abstract'=>'required',
'category'=>'',
'diaporama_dir'=>'',
'beg_date'=>'sometimes',
'end_date'=>'sometimes',
'close_date'=>'sometimes',
'receive_registration'=>'',
'sticky'=>'',
'user_id'=>'required',
'inscription_directive'=>''
]);
Post::create($validatedData);
session()->flash('message', 'Bravo ! Votre article a été enregistré.');
// $this->resetInputFields(); //user may want to keep the input stable
}
/**
* The attributes that are mass assignable.
*
* @var array
*/
public function edit($id)
{
$post = Post::findOrFail($id);
$this->post_id = $id;
$this->title = $post->title;
$this->abstract=$post->abstract;
$this->body=$post->body;
$this->category=$post->category;
$this->diaporama_dir=$post->diaporama_dir;
$this->beg_date=$post->beg_date;
$this->end_date=$post->end_date;
$this->close_date=$post->close_date;
$this->receive_registration=$post->receive_registration;
$this->sticky=$post->sticky;
$this->inscription_directive=$post->inscription_directive;
$this->dispatchBrowserEvent('notify','je passe en mode edit');//to switch browser page to edit mode
}
/**
* The attributes that are mass assignable.
*
* @var array
*/
public function update()
{
$validatedData = $this->validate([
'title' => 'required',
'body' => 'required',
'abstract'=>'required',
'category'=>'',
'diaporama_dir'=>'',
'beg_date'=>'sometimes',
'end_date'=>'sometimes',
'close_date'=>'sometimes',
'receive_registration'=>'',
'sticky'=>'',
'user_id'=>'required',
'inscription_directive'=>''
]);
$post = Post::find($this->post_id);
$post->update([
'title' => $this->title,
'body'=> $this->body,
'abstract'=> $this->abstract,
'category'=> $this->category,
'diaporama_dir'=>$this->diaporama_dir,
'beg_date'=>$this->beg_date,
'end_date'=>$this->end_date,
'close_date'=>$this->close_date,
'receive_registration'=>$this->receive_registration,
'sticky'=>$this->sticky,
'user_id'=>$this->user_id,
'inscription_directive'=>$this->inscription_directive
]);
session()->flash('message', "Bravo ! L'article a été mis à jour.");
// $this->resetInputFields();//user may like to keep the input fields stable
}
}
观点如下:
视图 1:resources/views/livewire/posts/posts 中的主页。blade.php
<div class="container m-auto w-10/12">
<div x-data="{ mode: 'list' }">
@if (session()->has('message'))
<div class="bg-green-200 p-4 w-full my-8 text-xl text-orange-500">
{{ session('message') }}
</div>
@endif
<div x-on:notify.window="mode = 'update'">
<div x-show="mode==='update'">
@include('livewire.posts.update')
</div>
<div x-show="mode === 'edit'">
@include('livewire.posts.create')
</div>
</div>
{{-- <div x-show="mode === 'list'" class="">--}}
<div>
<div>
<button x-on:click="mode = 'edit'" class="bg-red-400 px-2 py-1 border rounded-lg mt-2">Nouvel
article</button>
</div>
<table class=" bg-green-400 w-full table table-bordered mt-5 ">
<thead>
<tr class="bg-red-50 mb-2">
<th>Id.</th>
<th>Titre</th>
<th width="150px">Action</th>
</tr>
</thead>
<tbody>
@for ($i = 0; $i < $posts['per_page']; $i++)
<tr class="bg-red-400 mb-2 p-2 space-y-2 border-8 border-red-50 ">
<td>{{ $posts['data'][$i]['id'] }}</td>
<td>{{ $posts['data'][$i]['title'] }}</td>
<td>{{--les actions--}}
<button wire:click="edit({{ $posts['data'][$i]['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>
@endfor
</tbody>
</table>
<div class="flex flex-row mt-2">
@for ($i = 0; $i < count($links); $i++)
<div class="flex p-2 mr-2 border w-max-content">
<a href="{{$links[$i]['url'] }}">{{$links[$i]['label']}}</a>
</div>
@endfor
</div>
</div>
</div>
2- 创建包含在 resources/views/livewire/posts/create.blade.php
<div class="container bg-green-500 p-4">
<form>
This is the create form
<input type="hidden" name="user_id" wire:model="user_id" >
<div class="flex flex-col md:flex-row" >
<div class=" mt-2 flex flex-col w-max-content">
<label for="category">Catégorie:</label>
<select class="" name="category" id="category" wire:model="category">
<option value="Sans">Sans</option>
<option value="Annoncement">Annonce d'un événement</option>
</select>
@error('category') <span class="text-danger">{{ $message }}</span>@enderror
</div>
<div class=" mt-2 flex flex-col flex-auto ml-4">
<label for="title">Title:</label>
<input type="text" class="form-control" name="title" id="title" placeholder="Saisissez un titre"
wire:model="title" value="">
@error('title') <span class="text-danger">{{ $message }}</span>@enderror
</div>
</div>
<div class="flex flex-col md:flex-row" >
<div class=" mt-2 flex flex-col w-max-cbeg_date ">
<label for="beg_date">Date de début</label>
<input type="text" class="" name="beg_date" id="beg_date" wire:model="beg_date">
@error('beg_date') <span class="text-danger">{{ $message }}</span>@enderror
</div>
<div class=" mt-2 flex flex-col w-max-cbeg_date ml-4">
<label for="end_date">Datend_date</label>
<input type="text" class="" name="end_date" id="end_date" wire:model="end_date">
@error('end_date') <span class="text-danger">{{ $message }}</span>@enderror
</div>
<div class=" mt-2 flex flex-col w-max-cbeg_date ml-4">
<label for="close_dclose">Date limite</label>
<input type="text" class="" name="close_date" id="close_date" wire:model="close_date">
@error('close_date') <span class="text-danger">{{ $message }}</span>@enderror
</div>
<div class=" mt-2 flex flex-col w-max-content ml-4">
<label for="receive_registration">Accepte les inscriptions:</label>
<select class="" name="receive_registration" id="receive_registration" wire:model="receive_registration">
<option value="no">Non</option>
<option value="yes">Oui</option>
</select>
@error('receive_registration') <span class="text-danger">{{ $message }}</span>@enderror
</div>
<div class=" mt-2 flex flex-col flex-auto ml-4">
<label for="title">Dossier du diaporama</label>
<input type="text" class="form-control" name="diaporama_dir" id="diaporama_dir" placeholder="ex: admin/1"
wire:model="diaporama_dir">
@error('diaporama_dir') <span class="text-danger">{{ $message }}</span>@enderror
</div>
</div>
<div class="mt-2 flex flex-col">
<label for="abstract">Résumé</label>
<textarea class="form-control" name="abstract" id="abstract" wire:model="abstract"
placeholder="Saisissez votre article"></textarea>
@error('abstract') <span class="text-danger">{{ $message }}</span>@enderror
</div>
<div class="mt-2 flex flex-col">
<label for="body">Corps de l'article</label>
<textarea class="form-control" name="body" id="body" wire:model="body" rows=30
placeholder="Saisissez votre article"></textarea>
@error('body') <span class="text-danger">{{ $message }}</span>@enderror
</div>
<button wire:click.prevent="store()" class="bg-red-400 px-2 py-1 border rounded-lg mt-2">Enregistrer</button>
<button wire:click.prevent="resetInputFields()" class="bg-red-400 px-2 py-1 border rounded-lg mt-2">Effacer tout</button>
<button @click.prevent="mode = 'list'" class="bg-red-400 px-2 py-1 border rounded-lg mt-2 ml-16">Retour à la liste</button>
</form>
更新包括
除了 post id 的附加隐藏字段外,更新包含与创建包含完全相同。
发生了什么事?
在启动时,我的意思是当我访问 localhost:8000/posts 页面时,页面 1 正确显示并且 links在页面底部像 localhost:8000/posts?page=3 以页码为准。
从这个页面我通常可以使用底部 links 转到另一个页面,而且这几次。
点击link编辑post时出现问题。 post 由服务器正确发回,但我们立即 切换到分页 post 的第 1 页 和底部 link 奇怪的形式例如localhost:8000/livewire/message/posts.posts?page=3 无论页码是多少。
当我在显示创建表单后,在字段中键入第一个字符时,也会出现问题。事实上,它似乎每次需要同步时都会出现。
我该如何解决这个问题?
替换
<div class="flex flex-row mt-2">
@for ($i = 0; $i < count($links); $i++)
<div class="flex p-2 mr-2 border w-max-content">
<a href="{{$links[$i]['url'] }}">{{$links[$i]['label']}}</a>
</div>
@endfor
</div>
和
<div class="flex flex-row mt-2">
{{ $posts->links() }}
</div>
并在组件中
use WithPagination;