You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

提交Laravel Livewire表单导致另一展示组件消失问题

问题描述

我有一个带表单弹窗的添加组件,点击提交按钮后,用于展示数据的Display组件会从页面消失,即便触发dispatch('refreshList')事件也无法恢复显示。
Display组件是一个包含foreach循环的表格,它和添加组件在视图里只是上下排列的关系。控制台没有任何报错,所有请求都正常发送,但表格就是不见了。


添加组件的创建实体方法

public function storeWork()
{
    $this->validate();
    $this->time_from = new DateTime($this->date .' '.$this->day_start);
    list($hours, $minutes) = explode(':', $this->length);
    $this->time_to = (clone $this->time_from)->add(new DateInterval("PT{$hours}H{$minutes}M"));
    $work = $this->create();
    $this->dispatch('refreshList');
    session()->flash('success', 'Výkaz byl přidán.');
    $this->addNext();
}

public function render(){
    $orders = Order::where('state', "nevyrizena")->get();
    $employees = Employee::all();
    return view('livewire.WorkAddComponent', [
        'orders' => $orders, 
        'employees' => $employees,
        'types' => $this->types,
        'machines' => $this->machines,
        'categories' => $this->categories,
    ]);
}

添加组件的Blade视图

<div>
    <div x-data="{
        expanded: false,
        form: true,
        closeform() {
            this.expanded = false;
            this.form = true
        },
        openform() {
            this.expanded = true;
            this.form = true
        }
    }">
        <button class="btn" type="button" x-data x-on:click="openform()">
            ...
        </button>
        <div style="display: none;" x-show="expanded">
            <div class="fixed left-0 top-0 z-40 h-screen w-screen bg-gray-800/90"></div>
            <div class="fixed top-10 z-50 max-h-full w-full items-center justify-center" aria-hidden="true"
                 tabindex="-1">
                <div class="relative w-6/12 rounded-lg bg-gray-700 p-10 text-white shadow">
                    ...
                    <form wire:submit="storeWork">
                        @csrf
                        <div x-show="form">
                            <div class="mb-4">
                                ...
                            </div>
                            <div class="mb-4">
                                ...
                            </div>
                            <div class="mb-4">
                                ...
                            </div>
                            <div class="form-footer flex gap-3">**!!!这个按钮不会出问题!!!!**
                                <button class="btn" type="button" x-data
                                        x-on:click="form = false">继续</button>
                            </div>
                        </div>
                        <div x-show="!form">
                            <div class="mb-4">
                                ....
                            </div>
                            <div class="mb-4">
                                ...
                            </div>
                            <div class="mb-4">
                                ...
                            </div>
                            <div class="mb-4">
                                ...
                            </div>
                            <div class="mb-4">
                                ...
                            </div>
                            <div class="mb-4">
                                ...
                            </div>
                            <div class="form-footer flex gap-3"> **!!!这两个按钮都会导致问题**
                                <button class="btn-second-opt" type="submit" x-data x-on:click= "closeform()">保存并关闭</button>
                                <button class="btn" type="submit">保存并添加下一个</button>
                            </div>
                        </div>
                    </form>
                </div>
                @if (session('success'))
                    ...
            @endif
        </div>
    </div>
</div>

Display组件

#[On('refreshList')]
public function refresh(){}

public function render()
{
    $work = Work::where('date', $this->displayDate)->paginate(10);
    $people = Employee::all();
    return view('livewire.WorkDisplayComponent', [ 
        'work' => $work,
        'people' => $people,
    ]);
}

解决方案

1. 修复Alpine与Livewire的DOM冲突问题

提交按钮同时触发Alpine的closeform()和Livewire的表单提交,两者DOM操作互相干扰,导致Display组件DOM被意外移除。解决方式:

  • 在storeWork方法末尾添加Livewire事件,用来通知Alpine关闭弹窗:
    $this->dispatch('close-modal');
    
  • 在Blade视图的x-data容器上监听该事件:
    <div x-data="{...}" x-on:close-modal.window="closeform()">
    
  • 移除提交按钮上的x-on:click="closeform()",修改为:
    <button class="btn-second-opt" type="submit">保存并关闭</button>
    

2. 验证Display组件的日期状态

检查displayDate是否在刷新时被意外重置,导致查询无数据返回:

#[On('refreshList')]
public function refresh()
{
    // 确保displayDate为有效日期,比如默认当前日期
    if(empty($this->displayDate)) {
        $this->displayDate = now()->format('Y-m-d');
    }
}

3. 移除多余的CSRF标签

Livewire表单会自动处理CSRF防护,手动添加的@csrf可能引发异常,直接删除表单中的@csrf即可。


内容的提问来源于stack exchange,提问作者Leoš Nevoral

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.05 11:05:23