英文:
Vue - Wrong values when using multiple checkboxes and radio in paginated form
问题
I try to make a dynamic form using pagination. On each page there may be a collection of checkboxes or radio buttons. These are the answers options to questions. There may be one or multiple answers for a question, hence the radios and checkboxes. The given answers must be stored as a value to a parameter for each question. Everything seems to work fine as long as I use just radios or just checkboxes. As soon as I mix the two and use the pagination things get messed up. I made a VUE playground to illustrate the problem:
我尝试创建一个使用分页的动态表单。每一页可能有一组复选框或单选按钮。这些是问题的答案选项。每个问题可能有一个或多个答案,因此需要使用单选按钮和复选框。给定的答案必须存储为每个问题的参数值。只要我只使用单选按钮或只使用复选框,一切都运行正常。但一旦混合使用两者并使用分页,问题就会出现混乱。我创建了一个VUE示例来说明这个问题:
Above the inputs you see the result of de checkedNames var. If you move to the third question, you'll see this var also holds the answers to the second question.
在输入框上方,您可以看到checkedNames变量的结果。如果您跳转到第三个问题,您会发现此变量也包含了第二个问题的答案。
I also have an example without the pagination. There everything works as expected:
我还有一个没有分页的示例。在那里,一切都按预期工作:
Does anybody know what's wrong with my script?
有谁知道我的脚本有什么问题吗?
<script>
export default {
data() {
return {
formPosition: 0,
groups:[{
title: 'girls',
checkedNames: [],
type: 'checkbox',
names: ['Mary','Emma','Olivia']
},
{
title: 'boys',
checkedNames: [],
type: 'checkbox',
names: ['Jack','John','Mike']
},
{
title: 'Choose one',
checkedNames: '',
type: 'radio',
names: ['Red','Green','Yellow','Purple']
}]
}
},
methods: {
nextStep(){
setTimeout(() => {
this.formPosition += 1;
}, 400);
},
prevStep(){
setTimeout(() => {
this.formPosition -= 1;
}, 400);
}
}
}
</script>
<template>
<div id="'section' + formPosition">
<h4>
{{ groups[formPosition].title }}
</h4>
<div>Checked names: {{ groups[formPosition].checkedNames }}</div>
<ul>
<li v-for="(name, idx) in groups[formPosition].names" :key="'answer' + idx">
<input :type="groups[formPosition].type" :id="name" :value="name" :name="'question' + name" v-model="groups[formPosition].checkedNames" />
<label :for="name">{{ name }}</label>
</li>
</ul>
<div class="form-actions">
<button
class="btn btn-primary"
v-if="formPosition !== 0"
@click="prevStep">
‹ Previous
</button>
<button
class="btn btn-primary"
v-if="formPosition !== groups.length"
@click="nextStep">
Next ›
</button>
</div>
</div>
</template>
英文:
I try to make a dynamic form using pagination. On each page there may be a collection of checkboxes or radio buttons. These are the answers options to questions. There may be one or multiple answers for a question, hence the radios and checkboxes. The given answers must be stored as a value to a parameter for each question. Everything seems to work fine as long as I use just radios or just checkboxes. As soon as I mix the two and use the pagination things get messed up. I made a VUE playground to illustrate the problem:
Above the inputs you see the result of de checkedNames var. If you move to the third question, you'll see this var also holds the answers to the second question.
I also have an example without the pagination. There everything works as expected:
Doe anybody know what's wrong with my script?
<script>
export default {
data() {
return {
formPosition: 0,
groups:[{
title: 'girls',
checkedNames: [],
type: 'checkbox',
names: ['Mary','Emma','Olivia']
},
{
title: 'boys',
checkedNames: [],
type: 'checkbox',
names: ['Jack','John','Mike']
},
{
title: 'Choose one',
checkedNames: '',
type: 'radio',
names: ['Red','Green','Yellow','Purple']
}]
}
},
methods: {
nextStep(){
setTimeout(() => {
this.formPosition += 1;
}, 400);
},
prevStep(){
setTimeout(() => {
this.formPosition -= 1;
}, 400);
}
}
}
</script>
<template>
<div id="'section' + formPosition">
<h4>
{{ groups[formPosition].title }}
</h4>
<div>Checked names: {{ groups[formPosition].checkedNames }}</div>
<ul>
<li v-for="(name, idx) in groups[formPosition].names" :key="'answer'+ idx">
<input :type="groups[formPosition].type" :id="name" :value="name" :name="'question'+ name" v-model="groups[formPosition].checkedNames" />
<label :for="name">{{ name }}</label>
</li>
</ul>
<div class="form-actions">
<button
class="btn btn-primary"
v-if="formPosition !== 0"
@click="prevStep">
&lsaquo; Previous
</button>
<button
class="btn btn-primary"
v-if="formPosition !== groups.length"
@click="nextStep">
Next &rsaquo;
</button>
</div>
</div>
</template>
答案1
得分: 1
我意识到收音机元素与复选框元素不同,尽管在代码中只是类型发生了变化。即使外观发生了变化,初始化的元素行为可能没有改变。所以我改变了我的代码的这部分:
从这个:
<li v-for="(name, idx) in groups[formPosition].names" :key="'answer'+ idx">
<input :type="groups[formPosition].type" :id="name" :value="name" :name="'question'+ name" v-model="groups[formPosition].checkedNames" />
<label :for="name">{{ name }}</label>
</li>
改为这个:
<li v-for="(name, idx) in groups[formPosition].names">
<input v-if="groups[formPosition].type === 'checkbox'" type="checkbox" :id="name" :value="name" v-model="groups[formPosition].checkedNames" />
<input v-else type="radio" :id="name" :value="name" v-model="groups[formPosition].checkedNames" />
<label :for="name">{{ name }}</label>
</li>
现在它按预期工作。
英文:
I realised the radio element is not the same as a checkbox element even though in code it's just the type that changes. And even though the appearance changed, the initiated element's behaviour did probably not change. So I changed this part of my code:
<li v-for="(name, idx) in groups[formPosition].names" :key="'answer'+ idx">
<input :type="groups[formPosition].type" :id="name" :value="name" :name="'question'+ name" v-model="groups[formPosition].checkedNames" />
<label :for="name">{{ name }}</label>
</li>
to this:
<li v-for="(name, idx) in groups[formPosition].names">
<input v-if="groups[formPosition].type === 'checkbox'" type="checkbox" :id="name" :value="name" v-model="groups[formPosition].checkedNames" />
<input v-else type="radio" :id="name" :value="name" v-model="groups[formPosition].checkedNames" />
<label :for="name">{{ name }}</label>
</li>
And now it's working as expected
答案2
得分: 1
这是要翻译的内容:
"It's a problem with reactivity and the inputs and their bound v-model not updating properly. Since every page has a unique formPosition
, adding that as a key
to the component root div should help Vue's reactivity system understand when to update. Keeping all your same code, change just the first div:
<div id="'section' + formPosition" :key="formPosition">
```"
<details>
<summary>英文:</summary>
It's a problem with reactivity and the inputs and their bound v-model not updating properly. Since every page has a unique `formPosition`, adding that as a `key` to the component root div should help Vue's reactivity system understand when to update. Keeping all your same code, change just the first div:
```html
<div id="'section' + formPosition" :key="formPosition">
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论