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

如何使用Vue与Inertia提交含多行表格的表单?

动态多行表格表单提交方案(Vue.js + InertiaJS + Laravel)

问题场景

基于Vue.js、InertiaJS和Laravel开发项目,现有一个由后端返回交易数据填充的多行表格表单,每行包含账户名称、描述、金额字段,展示功能正常。需要实现:允许用户修改每行输入值,点击保存按钮后,通过InertiaJS将所有行的当前输入值发送至后端处理并存储到数据库。

查阅InertiaJS文档得知,useForm或reactive通常用于预定义字段的表单,但动态多行表格的字段是动态生成的,现有示例无法直接适配,因此需要针对性方案。

解决方案

核心思路:不直接修改props中的只读数据,先将后端返回的交易数据复制到本地响应式数组中,修改操作绑定到本地数组元素,提交时将整个数组作为表单数据发送。同时可结合Inertia的useForm实现表单状态管理(加载状态、错误处理等)。

修改后的完整代码

<script setup>
import AuthenticatedLayout from '@/Layouts/AuthenticatedLayout.vue';
import { Head, router, useForm } from '@inertiajs/vue3';
import { ref } from "vue";

const props = defineProps({
    Transactions: {
        type: Array, // 修正:交易数据应为数组类型,原代码写为Object错误
        required: true
    },
    Accounts: {
        type: Array, // 修正:账户列表应为数组类型,原代码写为Object错误
        required: true
    },
})

// 复制后端交易数据到本地响应式数组,避免直接修改props
const localTransactions = ref([...props.Transactions])

// 用useForm包裹交易数组,获得表单状态管理能力
const form = useForm({
    transactions: localTransactions.value
})

function submit() {
    // 提交到后端批量更新路由,替换为你的实际路由
    form.post('/transactions/bulk-update', {
        onSuccess: () => {
            // 提交成功后的操作,比如刷新页面或提示
            router.reload()
        },
        onError: (errors) => {
            // 错误处理逻辑
            console.error(errors)
        }
    })
}
</script>

<template>
    <AuthenticatedLayout>
        <div class="py-12">
            <div class="mx-auto max-w-8xl sm:px-6 lg:px-8">
                <div class="overflow-scroll bg-white shadow-sm sm:rounded-lg">
                    <form @submit.prevent="submit">
                        <table class="table-auto w-full">
                            <thead>
                                <tr>
                                    <th class="text-left p-3">Account</th>
                                    <th class="text-left p-3">Description</th>
                                    <th class="text-right p-3">Amount</th>
                                </tr>
                            </thead>
                            <tbody>
                                <!-- 用index绑定本地数组元素,确保v-model正确关联 -->
                                <tr v-for="(transaction, index) in localTransactions" :key="transaction.id || index">
                                    <td class="p-3">
                                        <select v-model="localTransactions[index].account_id">
                                            <option 
                                                v-for="account in Accounts" 
                                                :key="account.id"
                                                :value="account.id"
                                            > 
                                                {{ account.name }} 
                                            </option>
                                        </select>
                                    </td>
                                    <td class="p-3">
                                        <input 
                                            type="text" 
                                            v-model="localTransactions[index].description" 
                                            class="w-full text-left"
                                        >
                                    </td>
                                    <td class="p-3">
                                        <input 
                                            type="number" 
                                            v-model="localTransactions[index].amount" 
                                            class="w-full text-right"
                                        >
                                    </td>
                                </tr>
                            </tbody>
                        </table>

                        <button 
                            type="submit" 
                            :disabled="form.processing"
                            class="mb-4 mt-6 ml-3 inline-block rounded-md bg-blue-500 px-4 py-3 text-xs font-semibold uppercase tracking-widest text-white shadow-sm hover:bg-blue-600 disabled:opacity-50"
                        >
                            {{ form.processing ? 'Saving...' : 'Save' }}
                        </button>
                    </form>
                </div>
            </div>
        </div>
    </AuthenticatedLayout>
</template>

关键说明

  1. 数据隔离:将props中的Transactions复制到本地响应式数组localTransactions,避免直接修改Vue只读的props数据
  2. 表单状态管理:通过useForm包裹交易数组,获取processing状态控制按钮禁用状态和文本,同时支持成功/错误回调
  3. 字段绑定:使用数组索引index绑定输入框的v-model,确保每个输入值正确关联到本地数组的对应交易项
  4. 后端适配:提交路由需对应Laravel的批量更新接口,示例如下:

Laravel后端处理示例

// routes/web.php
Route::post('/transactions/bulk-update', [TransactionController::class, 'bulkUpdate'])->middleware('auth');

// app/Http/Controllers/TransactionController.php
public function bulkUpdate(Request $request)
{
    // 验证提交的交易数据
    $validated = $request->validate([
        'transactions.*.id' => 'required|exists:transactions,id',
        'transactions.*.account_id' => 'required|exists:accounts,id',
        'transactions.*.description' => 'required|string',
        'transactions.*.amount' => 'required|numeric',
    ]);

    // 批量更新交易数据
    foreach ($validated['transactions'] as $transactionData) {
        \App\Models\Transaction::where('id', $transactionData['id'])
            ->update([
                'account_id' => $transactionData['account_id'],
                'description' => $transactionData['description'],
                'amount' => $transactionData['amount'],
            ]);
    }

    return redirect()->back()->with('success', '交易数据更新成功');
}

内容的提问来源于stack exchange,提问作者Dave33

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.13 15:23:20