javascript - 如何从具有多个组件的动态表单中 $emit 数据
问题描述
我正在开发一个用户可以创建任务列表的应用程序。创建后,将从数据库中提取列表供用户使用,并为每个任务选择适当的响应。
回应: - 是或否
选择“否”:启用原因下拉列表以选择任务未完成的原因 - 选择“其他”选项将显示自定义原因输入框。
用户还可以为每个任务添加评论,一旦表单完成,他们就可以提交它。
由于显示每个任务的组件是多么动态,我不知道如何捕获表单响应。我<form>
在组件周围创建了一个 - 一旦单击应该提交表单,但我不知道如何从组件中获取数据。
应用程序.vue
<template>
<button @click="toggleComplete">Complete All</button>
<form @submit.prevent="submitModal">
<checklist-item
v-for="taskList in myChecklist.tasks.data"
:key="taskList.id"
:taskDetails="taskList"
:marked="markAll"
>
</checklist-item>
<div class="">
<button class="" type="submit">Submit</button>
</div>
</form>
</template>
<script>
import checklistItem from "./components/checklistItem.vue";
export default {
name: "App",
components: {
checklistItem,
},
data() {
return {
markAll: false,
myChecklist: {
success: true,
name: "Checklist 1",
roomId: 1,
notes: "Notes about the checklist",
tasks: {
data: [
{
id: 1,
name: "Task 1",
frequency: "D",
status: null,
comment: null,
reason: null,
updated_at: "2021-08-09",
},
{
id: 2,
name: "Task 2",
frequency: "M",
status: null,
comment: null,
reason: null,
updated_at: "2021-08-09",
},
{
id: 3,
name: "Task 3",
frequency: "Y",
status: null,
comment: null,
reason: null,
updated_at: "2021-08-09",
},
],
},
},
};
},
methods: {
toggleComplete() {
this.markAll = !this.markAll;
},
submitModal() {
console.log("inside");
},
},
};
</script>
<style>
</style>
清单项.vue
<template>
<div class="flex justify-center items-center">
<div
class="border border-gray-200 w-11/12 bg-white rounded-lg shadow-sm hover:shadow-2xl duration-500 px-2 py-4 my-1"
>
<div class="flex flex-col m-auto w-11.5/12">
<div class="">
<div class="text-xl font-semibold">
{{ taskDetails.name }}
</div>
<div class="pb-2 sm-pb-0">
<p>Due: <strong>Today</strong></p>
</div>
<!-- Yes Button -->
<div class="yesClass flex justify-center-0 pb-2">
<input
@change="disableSelect()"
type="radio"
:checked="marked"
:name="taskDetails.id"
:id="taskDetails.id + 'yes'"
class=""
/>
<label
:for="taskDetails.id + 'yes'"
class="yesClass border text-center border-orange-400 rounded-2xl w-full py-0.5 hover:bg-green-400 hover:text-white hover:border-green-200"
>
<span>Yes</span>
</label>
</div>
<!-- No Button -->
<div class="noClass flex justify-center pb-2">
<input
@change="enableSelect()"
type="radio"
:name="taskDetails.id"
:id="taskDetails.id + 'no'"
class=""
/>
<label
:for="taskDetails.id + 'no'"
class="border text-center border-orange-400 rounded-2xl w-full py-0.5 label-checked:bg-green-200 hover:bg-red-800 hover:text-white hover:border-red-200"
>
<span>No</span>
</label>
</div>
<!-- Reason Dropdown -->
<p>Reason:</p>
<div class="disabled flex justify-center">
<br />
<select
:disabled="!notCompletedToggle"
name="reason"
id="reasons"
class="w-full mt-1 rounded-lg py-0.5 my-0.5"
:class="[notCompletedToggle ? 'bg-red-500' : '']"
ref="selectedItem"
@change="customEventToggle($event)"
>
<option value="reason_1" :selected="!notCompletedToggle">
Select Reason
</option>
<option value="reason_1">Reason 1</option>
<option value="reason_2">Reason 2</option>
<option value="reason_3">Reason 3</option>
<option value="other">Other --></option>
</select>
</div>
<div
class="flex justify-center my-0.5"
:class="{ hidden: !customReasonToggle }"
>
<input
type="text"
class="bg-gray-200 w-full rounded-md mt-1 py-0.5"
v-model="customReason"
/>
</div>
</div>
<div class="">
<div class="flex items-end justify-start text-grey">
<label>Comment:</label>
</div>
<div class="flex items-end justify-center">
<textarea
type="text"
class="bg-gray-200 rounded-lg w-full h-16"
></textarea>
</div>
</div>
</div>
</div>
</div>
</template>
<script>
export default {
components: {},
emits: ["custom-event-toggle"],
props: ["taskDetails", "marked"],
data() {
return {
notCompletedToggle: false,
customReasonToggle: false,
customReason: "",
};
},
methods: {
customEventToggle(event) {
if (event.target.value === "other") {
this.customReasonToggle = true;
} else {
this.customReasonToggle = false;
}
},
disableSelect() {
this.notCompletedToggle = false;
this.customReasonToggle = false;
},
enableSelect() {
this.notCompletedToggle = true;
},
},
};
</script>
<style scoped>
input[type="radio"] {
display: none;
}
.yesClass input[type="radio"]:checked + label {
background-color: #78be20;
color: white;
}
.noClass input[type="radio"]:checked + label {
background-color: #da291c;
color: white;
}
</style>
解决方案
checklist-item
您可以在每个事件上从组件内部发出事件,以设置myChecklist.tasks.data
数组中的值。
methods: {
updateData(property, value) {
this.$emit("update-form-data", {
id: this.taskDetails.id,
property,
value,
});
},
customEventToggle(event) {
this.updateData("reason", event.target.value);
if (event.target.value === "other") {
this.customReasonToggle = true;
} else {
this.customReasonToggle = false;
}
},
disableSelect() {
this.updateData("status", "YES");
this.notCompletedToggle = false;
this.customReasonToggle = false;
},
enableSelect() {
this.updateData("status", "NO");
this.notCompletedToggle = true;
},
setComment(event) {
this.updateData("comment", event.target.value);
},
}
然后在父组件中监听事件并更新你的数据数组:
<checklist-item
v-for="taskList in myChecklist.tasks.data"
:key="taskList.id"
:taskDetails="taskList"
:marked="markAll"
@update-form-data="
this.myChecklist.tasks.data.find((task) => task.id === $event.id)[
$event.property
] = $event.value
"
这是您更新的沙盒。单击提交时将数据记录到控制台。
推荐阅读
- c# - 关于 UWP 上 DataGrid 的文档不清楚
- python-3.x - 当另一个 tkinter 打开时,单选按钮行为异常
- android - CMake与服务器通信发生错误
- excel - 无法使用调用的函数使用 VBA 创建时间戳
- azure - 在 PowerShell Runbook 中使用 Azure 文件共享
- c - 如何在函数声明中使用省略号在 C 中获取调用者函数名称?
- arrays - 如何使用jq将json项目值映射到兄弟数组
- postgresql - 如何用 * 屏蔽字符串中存在的第 N 个位置值
- powershell - 如何在PowerShell中用空格分割变量
- python - 如何对函数进行矢量化以加快对数据帧的操作?