我正在开发一个 VUE 应用程序。该应用程序的一部分是显示一个表(团队),其中包含来自后端的信息(由 axios / django rest_framework 提供)。这一切都有效。
当我单击“nieuwe categorie”时,模式会打开一个表单。 Onsubmit时,使用函数“submitHandler”。但是,在该函数中我无法获取表单数据?我需要用 axios 将其“POST”到后端....
我在模态形式上尝试过 v-model,但给出了参考错误。
无论如何,任何帮助将不胜感激。
模态组件:
<script setup>
import { defineProps, defineEmits, ref } from "vue";
import { onClickOutside } from '@vueuse/core'
const offset = 6
const props = defineProps({
isOpen: Boolean,
isTest: String,
Categorie: String,
modalAction: String,
});
const emit = defineEmits(["modal-close"]);
const target = ref(null)
onClickOutside(target, () => emit('modal-close'))
</script>
<template>
<div v-if="isOpen" class="modal-mask">
<div class="modal-wrapper">
<div class="modal-container" ref="target">
<div class="modal-header py-5">
<slot name="header">
<div v-if="modalAction === 'new'">
<h1>Nieuwe Categorie</h1>
</div>
<div v-else-if="modalAction === 'edit'"> {{ Categorie }}</div>
</slot>
</div>
<div class="modal-body">
<slot name="content">
<div class="mx-2" v-if="modalAction === 'new'">
<form class="w-full" @submit.prevent="submitHandler">
<div class="flex -mx-2">
<div class="items-center border-b border-teal-500 py-2 px-2">
<label
class="block uppercase tracking-wide text-gray-700 text-xs font-bold mb-2"
for="grid-first-name">
Categorie
</label>
<select
class="appearance-none bg-transparent border-none w-full text-gray-700 mr-3 py-1 px-2 leading-tight focus:outline-none"
placeholder="1:1" aria-label="">
<option v-for="n in 14">Onder-{{ n + offset }}
</option>
</select>
</div>
</div>
<div class="flex -mx-2">
<div class="w-full items-center border-b border-teal-500 py-2 px-2">
<label
class="block uppercase tracking-wide text-gray-700 text-xs font-bold mb-2"
for="grid-first-name">
T/M geboortejaar
</label>
<select
class="appearance-none bg-transparent border-none w-full text-gray-700 mr-3 py-1 px-2 leading-tight focus:outline-none"
placeholder="1:1" aria-label="">
<option v-for="n in 14">{{ n + 2003 }}</option>
</select>
</div>
<div class="w-10"></div>
<div class="w-full items-center border-b border-teal-500 py-2 px-2">
<label
class="block uppercase tracking-wide text-gray-700 text-xs font-bold mb-2"
for="grid-first-name">
Aantal veldspelers
</label>
<select
class="appearance-none bg-transparent border-none w-full text-gray-700 mr-3 py-1 px-2 leading-tight focus:outline-none"
placeholder="1:1" aria-label="">
<option>4</option>
<option>6</option>
<option>8</option>
<option>11</option>
</select>
</div>
</div>
<div class="flex -mx-2">
<div class="items-center w-full border-b border-teal-500 py-2 px-2">
<label
class="block uppercase tracking-wide text-gray-700 text-xs font-bold mb-2"
for="grid-first-name">
Veldomvang
</label>
<select
class="appearance-none bg-transparent border-none w-full text-gray-700 mr-3 py-1 px-2 leading-tight focus:outline-none"
type="select" placeholder="1:1" aria-label="veld">
<option>1:8</option>
<option>1:4</option>
<option>1:2</option>
<option>1:1</option>
</select>
</div>
<div class="w-10"></div>
<div class="items-center w-full border-b border-teal-500 py-2 px-2">
<label
class="block uppercase tracking-wide text-gray-700 text-xs font-bold mb-2"
for="grid-first-name">
Wedstrijdduur
</label>
<select
class="appearance-none bg-transparent border-none w-full text-gray-700 mr-3 py-1 px-2 leading-tight focus:outline-none"
placeholder="1:1" aria-label="">
<option>12</option>
<option>2x20 (na 10min time-out)</option>
<option>2x25 (na 12,5min time-out)</option>
<option>2x30 (na 15min time-out)</option>
<option>2x30</option>
<option>2x35</option>
<option>2x40</option>
<option>2x45</option>
</select>
</div>
</div>
<div class="flex -mx-2">
<div class="w-full items-center border-b border-teal-500 py-2 px-2">
<label
class="block uppercase tracking-wide text-gray-700 text-xs font-bold mb-2"
for="grid-first-name">
Dispensatie
</label>
<select
class="appearance-none bg-transparent border-none w-full text-gray-700 mr-3 py-1 px-2 leading-tight focus:outline-none"
placeholder="1:1" aria-label="">
<option v-for="n in 3">{{ n }}</option>
</select>
</div>
<div class="w-10"></div>
<div class="w-full items-center border-b border-teal-500 py-2 px-2">
<label
class="block uppercase tracking-wide text-gray-700 text-xs font-bold mb-2"
for="grid-first-name">
Actief binnen club
</label>
<input
class="appearance-none bg-transparent border-blue text-gray-700 mr-3 py-1 px-2 leading-tight focus:outline-none"
type="checkbox" placeholder="1" aria-label="dispensatie">
</input>
</div>
</div>
</form>
</div>
</slot>
</div>
<div class="modal-footer">
<slot name="footer">
<div>
<!--<button @click.stop="emit('modal-close')">Submit</button>-->
<button>Submit</button>
</div>
</slot>
</div>
</div>
</div>
</div>
</template>
<script>
</script>
<style scoped>
.modal-mask {
position: fixed;
z-index: 9998;
top: 0;
left: 0;
width: 100%;
height: 100%;
background-color: rgba(0, 0, 0, 0.5);
}
.modal-container {
width: 800px;
margin: 150px auto;
padding: 20px 30px;
background-color: #fff;
border-radius: 2px;
box-shadow: 0 2px 8px rgba(0, 0, 0, 0.33);
}
</style>
和景色:
<script setup>
import { ref } from "vue";
import ModalComponent from "../components/ModalComponent.vue";
import axios from 'axios'
const isModalOpened = ref(false);
const test = ref('')
const editCategorie = ref('')
const modalAction = ref('new')
const form = ref([])
const openModal = (cat, action) => {
if (!action) {
console.log('action: ', action)
action = 'new'
}
modalAction.value = action
editCategorie.value = cat.categorie
isModalOpened.value = true;
};
const closeModal = () => {
isModalOpened.value = false;
};
const submitHandler = () => {
//here I should be able to get the form data
console.log('data:', this.form) //this gives an error 'form not defined'
}
</script>
<template>
<div class="p-2 pt-20 sm:ml-64">
<div class="p-4 border-2 border-gray-200 border-dashed bg-gray-200 rounded-lg dark:border-gray-700 mt-14">
<!-- CRUD table goes here-->
<!-- Start block -->
<section class="bg-gray-50 dark:bg-gray-900 p-3 sm:p-5 antialiased">
<div class="mx-auto max-w-screen-xl px-4 lg:px-12">
<!-- Start coding here -->
<div class="bg-white dark:bg-gray-800 relative shadow-md sm:rounded-lg overflow-hidden">
<div
class="flex flex-col md:flex-row items-center justify-between space-y-3 md:space-y-0 md:space-x-4 p-4">
</div>
<div class="overflow-x-auto">
<table class="w-full text-sm text-left text-gray-500 dark:text-gray-400">
<thead
class="text-xs text-gray-700 uppercase bg-gray-50 dark:bg-gray-700 dark:text-gray-400">
<tr>
<th scope="col" class="px-4 py-3">Actief binnen club</th>
<th scope="col" class="px-4 py-3">Categorie</th>
<th scope="col" class="px-4 py-3">t/m geboortejaar</th>
<th scope="col" class="px-4 py-3">Max. aantal veldspelers</th>
<th scope="col" class="px-4 py-3">Veldomvang</th>
<th scope="col" class="px-4 py-3">Wedstrijdduur</th>
<th scope="col" class="px-4 py-3">Dispensatie</th>
<th scope="col" class="px-4 py-3">Wijzig</th>
</tr>
</thead>
<tbody v-for="cat in teamcats">
<tr class="border-b dark:border-gray-700">
<td class="px-4 py-3">
<input v-model="cat.actief" type="checkbox" />
</td>
<th scope="row"
class="px-4 py-3 font-medium text-gray-900 whitespace-nowrap dark:text-white">
{{ cat.categorie }}</th>
<td class="px-4 py-3">{{ cat.geboortejaar }}</td>
<td class="px-4 py-3">{{ cat.veldspelers }}</td>
<td class="px-4 py-3 max-w-[12rem] truncate">{{ cat.veldomvang }}</td>
<td class="px-4 py-3">{{ cat.wedstrijdduur }}</td>
<td class="px-4 py-3">{{ cat.dispensatie }}</td>
<td class="px-4 py-3"><button class="bg-blue-300"
@click="openModal(cat, mode = 'edit')">Wijzig</button>
</td>
</tr>
</tbody>
</table>
</div>
<div class="flex flex-col italic md:flex-row justify-between items-start md:items-center space-y-3 md:space-y-0 p-4"
aria-label="Table navigation">
<span class="text-sm font-normal text-gray-500 dark:text-gray-400">
Datum laatste wijziging:
<span class="font-semibold text-gray-900 dark:text-white">22-03-2024</span>
</span>
<div>
<!-- Modal toggle -->
<div>
<!--<button @click="openModal">Toevoegen Categorie</button>-->
<button @click="openModal">Toevoegen Categorie</button>
</div>
</div>
</div>
</div>
<!-- modal-->
<ModalComponent :isOpen="isModalOpened" :modalAction="modalAction" :Categorie="editCategorie"
@modal-close="closeModal" @submit="submitHandler" name="first-modal">
<template #header></template>
<template #content></template>
<template #footer><button @click="submitHandler">submit</button></template>
</ModalComponent>
<!-- modal-->
</div>
</section>
<!-- End block -->
<!-- END OF CRUD Table-->
</div>
</div>
</template>
<script>
import axios from 'axios'
import TestView from "./TestView.vue";
export default {
data() {
return {
teamcats: [],
}
},
mounted() {
this.getTeamCats()
},
methods: {
getTeamCats() {
axios
.get('/api/team/view')
.then(response => {
console.log(response.data)
this.teamcats = response.data
})
.catch(error => {
console.log('error', error)
})
},
}
}
</script>
您可以使用emit将数据传递到表格组件
在模态组件中,定义另一个发射。为此改变这一行
const emit = defineEmits(["modal-close"]);
到这里
const emit = defineEmits(["modal-close", "submit"]);
.
然后定义一个函数来发出此事件和数据。目前,您的模态中没有数据模型,您需要先创建它并将其与 v-model 绑定到控件。
const submit = () => {
emit('submit', data);
}
我看到您已经覆盖了页脚插槽,要么撤消该操作并从现有按钮调用提交函数,要么将提交函数提供为作用域插槽(插槽上的 v-bind)。然后你也可以在你的桌子上使用它。
<slot name="footer" v-bind="{ submit }">
<button @click.prevent="submit">Submit</button>
</slot>
在你的表中,让submitHandler函数强调一个参数,那就是数据。
const submitHandler = (data) => {
// do the things with axios
// close the modal
}
如果你想控制提交按钮,表格组件中模态框的页脚必须如下所示:
<template #footer="{ submit }"><button @click="submit">submit</button></template>