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>
核心原因
- 未实现v-model双向绑定逻辑:Vue 2中v-model的本质是
valueprop +input事件,你的组件既没有接收父组件传入的value,也没有在内部值变化时触发input事件通知父组件更新。 - 绑定值不匹配:你用
form.tara绑定组件,但组件内部有country/state/city三个独立值,单个变量无法承载多个字段的变化。 - 原生表单字段失效:子组件内的
<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
相关产品推荐
相关产品推荐

