LiveWire动态行字段更新时库存检查与前端状态同步问题
LiveWire动态订单行库存状态更新不生效的解决方案
问题根源
直接在updatedorderLines()中修改数组元素的checking值,LiveWire可能无法检测到集合/数组的内部变化;同时全局监听整个orderLines数组的更新会导致不必要的遍历,效率低下。
解决方案
1. 改用精准的字段更新钩子
移除全局的updatedorderLines()方法,使用LiveWire的数组字段更新钩子,针对单个订单行的package_id或amount变化触发库存检查,既高效又能正确触发响应式更新。
修改控制器代码:
// 移除原有的updatedorderLines(),替换为以下方法 public function updatedOrderLines($value, $key) { // 解析数组键,格式为"索引.字段名",比如"0.package_id" [$index, $field] = explode('.', $key); $orderLineRow = &$this->orderLines[$index]; // 仅在套餐ID或数量变化时执行库存检查 if (in_array($field, ['package_id', 'amount'])) { // 先设置为"检查中"状态 $this->orderLines[$index]['checking'] = 0; // 获取订单配送日期(替换为你实际的日期字段,比如$this->order->delivery_date) $deliveryDate = $this->order->delivery_date; $availableStock = $this->getStockOnDate($orderLineRow['package_id'], $deliveryDate); // 根据库存和订购数量更新状态 if ($availableStock >= $orderLineRow['amount']) { $this->orderLines[$index]['checking'] = 1; // 库存充足 } else { $this->orderLines[$index]['checking'] = 2; // 库存不足 } } // 更新当前订单行的数据库记录 $orderLine = OrderLine::find($orderLineRow['db_id']); $orderLine->package_id = $orderLineRow['package_id']; $orderLine->amount = $orderLineRow['amount']; $totals = PackagesController::packageCalculateTotals($orderLine->package_id); $orderLine->cost_ex_vat = $totals['customTotals']['price_ex_vat']; $orderLine->cost_inc_vat = $totals['customTotals']['price_inc_vat']; $orderLine->vat_9 = $totals['customTotals']['vat_9']; $orderLine->vat_21 = $totals['customTotals']['vat_21']; $orderLine->save(); // 重新计算订单总价(按需保留) $this->recalculateOrderTotal(); } // 单独封装订单总价计算逻辑 private function recalculateOrderTotal() { $orderTotal = 0; foreach ($this->orderLines as $row) { $line = OrderLine::find($row['db_id']); $orderTotal += $line->cost_ex_vat * $row['amount']; } // 若需要更新订单表的总价字段,可在此处处理 // $this->order->total = $orderTotal; // $this->order->save(); } // 确保库存查询方法可正常调用 private function getStockOnDate($packageId, $date) { // 替换为你的实际库存查询逻辑,返回可用库存数量 // 示例:return PackageStock::where('package_id', $packageId)->where('date', $date)->value('quantity'); }
2. 优化前端绑定(确保原有逻辑正确)
当前的Blade代码绑定逻辑已正确,只需确保每个订单行的索引$key唯一:
@foreach($orderLines as $key => $orderLine) <div class="disFlex fdCol row"> <div class="section__grid disGrid row disGrid--twoColumns--small pb10 mb5 bBottom--dashed"> <div class="section__row__col disFlex fdCol"> <label class="bold cBlack">Pakket: @if($orderLine['checking'] == 0) <div title="Voorraad aan het controleren..." style="height: 10px; width: 10px; " class="spinner"></div> @endif @if($orderLine['checking'] == 1) <i title="Pakket is op voorraad op de geselecteerde leverdatum" class="fal fa-check-circle cGreen"></i> @endif @if($orderLine['checking'] == 2) <i title="Pakket is niet op voorraad op de geselecteerde leverdatum" class="far fa-times-circle cRed"></i> @endif </label> <div class="selectWrapper row"> <select @if($order->is_exported) disabled @endif wire:model.lazy="orderLines.{{$key}}.package_id"> @foreach($packages as $package) <option value="{{$package->id}}">{{$package->name}}</option> @endforeach </select> </div> </div> <div class="section__row__col disFlex"> <div class="section__row__col disFlex fdCol row"> <label class="bold cBlack">Aantal:</label> <div class="row disFlex jcSB nw"> <input @if($order->is_exported) readonly @endif wire:model.lazy="orderLines.{{$key}}.amount" type="number" class="row"> @if(!$order->is_exported) <span wire:click="removeItem({{$key}})" data-pakket="true" class="btn red ml10"><i class="fal fa-trash-alt"></i></span> @endif </div> </div> </div> </div> </div> @endforeach
3. 强制触发响应式更新(可选)
如果遇到极端情况更新仍不生效,可使用LiveWire的set方法替代直接赋值,确保框架检测到变化:
// 替换直接赋值的代码 $this->set("orderLines.{$index}.checking", 0); // 检查中 // ... $this->set("orderLines.{$index}.checking", 1); // 库存充足 // ... $this->set("orderLines.{$index}.checking", 2); // 库存不足
内容的提问来源于stack exchange,提问作者luukd
相关产品推荐
相关产品推荐

