如何将模态组件中的表单数据获取到提交处理程序中

问题描述 投票:0回答:1

我正在开发一个 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>
javascript forms vue.js axios modal-dialog
1个回答
0
投票

您可以使用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>
© www.soinside.com 2019 - 2024. All rights reserved.