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

Laravel Vue表单提交时无法获取自定义下拉组件值求助

问题:Laravel+Vue表单提交时自定义下拉组件值无法传递

在Laravel+Vue项目中,表单内嵌入了自定义DropdownCountries组件,已绑定v-model="form.tara",但点击Save按钮提交表单时,下拉组件中的country、state、city值无法被提交。

表单代码

<form @submit.prevent="form.patch(route('profile.update.account'))" class="mt-6 space-y-6">
    <div>
        <InputLabel for="adresa" value="Adresa" />

        <TextInput
            id="adresa"
            type="text"
            class="mt-1 block w-full"
            v-model="form.adresa"
            required
            autofocus
            autocomplete="adresa"
        />

        <InputError class="mt-2" :message="form.errors.adresa" />
    </div>

    <DropdownCountries 
        id="tara"
        v-model="form.tara"
        required
        autocomplete="Romania"
    />

    <div class="flex items-center gap-4">
        <PrimaryButton :disabled="form.processing">Save</PrimaryButton>

        <Transition enter-from-class="opacity-0" leave-to-class="opacity-0" class="transition ease-in-out">
            <p v-if="form.recentlySuccessful" class="text-sm text-gray-600">Saved.</p>
        </Transition>
    </div>
</form>

自定义组件代码

<template>
    <div class="container">
        <div class="row justify-content-center" style="margin: 20px 0px 20px 0px;">
            <div class="col-md-8">
                <div class="card">
                    <div class="card-body">
                        <div class="form-group">
                            <select name="tara" class='form-control' v-model='country' @change='getStates()'>
                                <option value='0' >Select Country</option>
                                <option v-for='data in countries' :value='data.id'>{{ data.name }}</option>
                            </select>
                        </div>
                        <div class="form-group">
                            <select name="judet" class='form-control' v-model='state' @change='getCities()'>
                                <option value='0' >Select State</option>
                                <option v-for='data in states' :value='data.id'>{{ data.name }}</option>
                            </select>
                        </div>
                        <div class="form-group">
                            <select name="oras" class='form-control' v-model='city'>
                                <option value='0' >Select City</option>
                                <option v-for='data in cities' :value='data.id'>{{ data.name }}</option>
                            </select>
                        </div>
                    </div>
                </div>
            </div>
        </div>
    </div>
</template>

<script>
export default {
    data(){
        return {
            country: 180,
            countries: [],
            state: 0,
            states: [],
            city: 0,
            cities: [],
        }
    },
    methods:{
        getCountries: function(){
            axios.get('/api/tari')
                .then(function (response) {
                    this.countries = response.data;
                }.bind(this));
        },
        getStates: function() {
            axios.get('/api/judete/' + this.country).then(function(response){
                this.states = response.data;
            }.bind(this));
        },
        getCities: function() {
            axios.get('/api/orase/' + this.state).then(function(response) {
                this.cities = response.data
            }.bind(this));
        }
    },
    created: function(){
        this.getCountries()
    }
}
</script>

核心原因

  1. 未实现v-model双向绑定逻辑:Vue 2中v-model的本质是value prop + input事件,你的组件既没有接收父组件传入的value,也没有在内部值变化时触发input事件通知父组件更新。
  2. 绑定值不匹配:你用form.tara绑定组件,但组件内部有country/state/city三个独立值,单个变量无法承载多个字段的变化。
  3. 原生表单字段失效:子组件内的<select>设置的name属性,无法被父组件的Vue表单提交逻辑(如form.patch)识别,因为Vue表单依赖响应式数据而非原生DOM字段。

修复方案

1. 改造子组件,实现双向绑定

更新DropdownCountries组件,支持接收父组件的对象值,并在内部值变化时同步给父组件:

<template>
    <div class="space-y-4">
        <div class="form-group">
            <label>Tara</label>
            <select class='form-control' v-model='localCountry' @change='handleCountryChange'>
                <option value='0' >Select Country</option>
                <option v-for='data in countries' :value='data.id'>{{ data.name }}</option>
            </select>
        </div>
        <div class="form-group">
            <label>Judet</label>
            <select class='form-control' v-model='localState' @change='handleStateChange'>
                <option value='0' >Select State</option>
                <option v-for='data in states' :value='data.id'>{{ data.name }}</option>
            </select>
        </div>
        <div class="form-group">
            <label>Oras</label>
            <select class='form-control' v-model='localCity' @change='handleCityChange'>
                <option value='0' >Select City</option>
                <option v-for='data in cities' :value='data.id'>{{ data.name }}</option>
            </select>
        </div>
    </div>
</template>

<script>
export default {
    props: {
        value: {
            type: Object,
            default: () => ({ country: 180, state: 0, city: 0 })
        }
    },
    data() {
        return {
            localCountry: this.value.country,
            localState: this.value.state,
            localCity: this.value.city,
            countries: [],
            states: [],
            cities: []
        }
    },
    watch: {
        // 同步父组件传入的value变化到本地变量
        value(newVal) {
            this.localCountry = newVal.country
            this.localState = newVal.state
            this.localCity = newVal.city
        }
    },
    methods: {
        getCountries() {
            axios.get('/api/tari').then(res => this.countries = res.data)
        },
        getStates() {
            axios.get('/api/judete/' + this.localCountry).then(res => this.states = res.data)
        },
        getCities() {
            axios.get('/api/orase/' + this.localState).then(res => this.cities = res.data)
        },
        // 触发input事件传递完整地址对象给父组件
        handleCountryChange() {
            this.$emit('input', { ...this.value, country: this.localCountry, state: 0, city: 0 })
            this.getStates()
        },
        handleStateChange() {
            this.$emit('input', { ...this.value, state: this.localState, city: 0 })
            this.getCities()
        },
        handleCityChange() {
            this.$emit('input', { ...this.value, city: this.localCity })
        }
    },
    created() {
        this.getCountries()
    }
}
</script>

2. 更新父组件表单绑定

修改父组件的form对象,用一个对象承载地址信息,并更新组件绑定:

<form @submit.prevent="form.patch(route('profile.update.account'))" class="mt-6 space-y-6">
    <!-- 其他字段... -->
    <div>
        <InputLabel value="Locatie" />
        <DropdownCountries 
            v-model="form.location"
            required
        />
    </div>
    <!-- 提交按钮... -->
</form>

初始化表单时添加location字段:

data() {
    return {
        form: this.$inertia.form({
            adresa: '',
            location: { country: 180, state: 0, city: 0 }
        })
    }
}

3. 后端接收参数

在Laravel控制器中接收完整的地址对象:

public function updateAccount(Request $request)
{
    $validated = $request->validate([
        'adresa' => 'required|string',
        'location.country' => 'required|integer',
        'location.state' => 'required|integer',
        'location.city' => 'required|integer',
    ]);

    auth()->user()->update([
        'adresa' => $validated['adresa'],
        'country_id' => $validated['location']['country'],
        'state_id' => $validated['location']['state'],
        'city_id' => $validated['location']['city'],
    ]);

    return redirect()->back()->with('success', 'Profil actualizat.');
}

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.11 02:05:21