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

Laravel Livewire单元格编辑后按钮与输入框无法隐藏求助

问题描述

使用Laravel Livewire开发产品数据展示表格,点击单元格时显示输入框、保存和取消按钮。点击保存或取消后数据可正常保存,但输入框与按钮仍未隐藏,尽管cancelEdit方法已重置editProductID和productQty字段。

相关代码

products.blade.php

<table class="w-full text-sm text-left rtl:text-right dark:text-gray-400">
    <thead class="text-xs text-gray-700 uppercase bg-gray-50 dark:bg-gray-700 dark:text-gray-400">
        <tr>
            <th scope="col" class="px-6 py-3">Qty</th>
        </tr>
    </thead>
    <tbody>
        <?php $i = 0 ?>
        @foreach($products as $product)
        <tr wire:key="{{$product->id}}" wire:poll class="odd:bg-white hover:bg-gray-50 odd:dark:bg-gray-900 even:bg-gray-50 even:dark:bg-gray-800 border-b dark:border-gray-700">
            <td class="px-6 py-2 text-center" wire:click="editQty({{$product->id}})">
                @if ($editProductID !== $product->id)
                    {{$product->p_qty}}
                @else
                    <input type="text" wire:model.defer="productQty" class="bg-gray-100 test-gray-900 text-sm rounded block w-full p-2" />
                    <div class="flex items-center space-x-2">
                        <button type="button" wire:confirm="Are you sure?" wire:click="updateQty" class="text-blue-700 border border-blue-700 hover:bg-white-700 hover:text-white focus:ring-4 focus:outline-none focus:ring-blue-300 font-medium rounded-full text-sm p-2 text-center inline-flex items-center dark:hover:text-white dark:focus:ring-blue-800 dark:hover:bg-blue-500">
                            <span class="sr-only">Edit</span>
                        </button>
                        <button type="button" wire:click="cancelEdit" class="text-blue-700 border border-blue-700 hover:bg-white-700 hover:text-white focus:ring-4 focus:outline-none focus:ring-blue-300 font-medium rounded-full text-sm p-2 text-center inline-flex items-center dark:border-blue-500 dark:text-blue-500 dark:hover:text-white dark:focus:ring-blue-800 dark:hover:bg-blue-500">
                            <span class="sr-only">Cancel</span>
                        </button>
                    </div>
                    @error("productQty")
                        {{$message}}
                    @enderror
                @endif
            </td>
        </tr>
        @endforeach
    </tbody>
    <tfoot>
        <tr class="font-semibold text-gray-900 dark:text-white">
            <th colspan="5" scope="row" class="px-6 py-3 text-base">Total</th>
            <td colspan="3" class="px-6 py-3">${{number_format($totalCost,0)}}</td>
            <td class="px-6 py-3">{{$totalQty}}</td>
        </tr>
    </tfoot>
</table>

Livewire组件代码

public $editProductID = null;

#[Rule('required|min:1|max:3')]
public $productQty = null;

public function updateQty() {
    $id = $this->editProductID;
    $this->validateOnly('productQty');

    Product::findOrFail($id)->update([
        'p_qty' => $this->productQty
    ]);

    $this->cancelEdit();
}

public function cancelEdit() {
    $this->reset('editProductID','productQty');
}

public function editQty($id) {
    $this->editProductID = $id;
    $this->productQty = Product::findOrFail($id)->p_qty;
}

public function render()
{
    $words = explode(' ', $this->search);
            
    foreach($words as $key => $word) {
        $words[$key] = 'keyword_build LIKE "%'.$word .'%" AND ';
    }
    $searchTerm = implode( ' ', $words);
    $searchTerm = substr($searchTerm,0,-5);
 
    if ($this->OnHand==1)
        $sign = ">=";
    else $sign = "<=";

    $products = Product::whereRaw($searchTerm)
        ->where('p_qty', $sign , $this->OnHand)
        ->orderBy($this->sortBy, $this->sortDirection);
        
    $totalQty = $products->sum('p_qty');
    $totalCost = $products->sum('p_price');

    $products = $products->paginate(perPage: 10);

    return view('livewire.products',["products"=>$products, 'totalCost' => $totalCost, 'totalQty' => $totalQty]);
}
解决方案

1. 阻止事件冒泡

问题核心是按钮点击事件冒泡到父级<td>,导致点击保存/取消按钮时,会同时触发<td>上的editQty方法,重新将editProductID设置为当前产品ID,从而输入框和按钮无法隐藏。

修改按钮的wire:click为wire:click.stop,阻止事件冒泡:

<!-- 保存按钮 -->
<button type="button" wire:confirm="Are you sure?" wire:click.stop="updateQty" class="text-blue-700 border border-blue-700 hover:bg-white-700 hover:text-white focus:ring-4 focus:outline-none focus:ring-blue-300 font-medium rounded-full text-sm p-2 text-center inline-flex items-center dark:hover:text-white dark:focus:ring-blue-800 dark:hover:bg-blue-500">
    <span class="sr-only">Edit</span>
</button>
<!-- 取消按钮 -->
<button type="button" wire:click.stop="cancelEdit" class="text-blue-700 border border-blue-700 hover:bg-white-700 hover:text-white focus:ring-4 focus:outline-none focus:ring-blue-300 font-medium rounded-full text-sm p-2 text-center inline-flex items-center dark:border-blue-500 dark:text-blue-500 dark:hover:text-white dark:focus:ring-blue-800 dark:hover:bg-blue-500">
    <span class="sr-only">Cancel</span>
</button>

2. 移除不必要的wire:poll

<tr>上的wire:poll会定期刷新组件,可能干扰状态的正常更新。如果不需要实时自动刷新数据,建议移除该指令:

<tr wire:key="{{$product->id}}" class="odd:bg-white hover:bg-gray-50 odd:dark:bg-gray-900 even:bg-gray-50 even:dark:bg-gray-800 border-b dark:border-gray-700">

3. 额外清除验证错误(可选)

如果仍存在状态异常,可在cancelEdit方法中清除验证错误信息,避免残留状态影响视图:

public function cancelEdit() {
    $this->reset('editProductID','productQty');
    $this->resetErrorBag(); // 清除验证错误
}

内容的提问来源于stack exchange,提问作者Edward B.

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.28 06:43:11