0

I have a parent component which has a child component which is used two times and the Child component uses the Vue draggable library. Now I want to reset the arrays which render the two child components draggable elements to its initial state, if the user drops an element into an array where the element is already in.

Child Component:

<script setup lang="ts">
import { Course, Timeslot } from "@/stores/enrollment";
import { PropType, ref } from "vue";
import { Enrollment } from "@/stores/enrollment";
import EnrolledListComponent from "./EnrolledListComponent.vue";
import { onMounted } from "vue";
import { watch } from "vue";
import draggable from "vuedraggable";
import { User } from "@/stores/user";

const props = defineProps({
    enrollment: {
        type: Object as PropType<Enrollment>,
        required: true,
    },
    timeslotStudentMap: {
        type: Object,
        required: true,
    },
    isRight: {
        type: Boolean,
        required: true,
    },
});

const emit = defineEmits(["update:timeslotStudentMap"]);

function updateEnrolledUser() {
    const timeslotID = timeslot.value?.uutime_slot_id;
    enrolledUsers.value = timeslotID
        ? props.timeslotStudentMap.get(timeslotID)
        : [];
}

function updateTimeslotStudentMap(item: any) {
    const timeslotID = timeslot.value?.uutime_slot_id;
    if (timeslotID) {
        if(item.added != undefined) {
            if(checkIfUserIsEnrolled(props.timeslotStudentMap.get(timeslotID), item.added.element.userID)) {
                alert("Student ist bereits in diesem Kurs.");
                return;
            } 
        }
    }
    props.timeslotStudentMap.set(timeslotID, enrolledUsers.value);
    emit("update:timeslotStudentMap", props.timeslotStudentMap);
    updateEnrolledUser();
}

function checkIfUserIsEnrolled(users: User[], userID: number) {
    for (let i = 0; i < users.length; i++) {
        if (users[i].userID == userID) return true;
    }
    return false;
    
}


</script>

<template>
    <div class="w-5/12 border-2 border-gray-600 bg-violet-100 rounded-lg p-3">
        <div class="border-b-2 flex flex-col border-gray-500 pb-3">
            <select
                v-model="course"
                name="course"
                class="bg-pink-300 border-2 border-gray-600 rounded-sm p-1 w-full"
            >
                <option
                    v-for="(course, index) in enrollment.courses"
                    :key="index"
                    :value="course"
                >
                    {{ course.name }}
                </option>
            </select>
            <select
                v-model="timeslot"
                name="course"
                class="bg-violet-300 border-2 w-full border-gray-600 rounded-sm p-1 mt-1"
            >
                <option
                    v-for="(timeslot, index) in course?.timeslots"
                    :key="index"
                    :value="timeslot"
                >
                    {{ timeslot.weekday }} |
                    {{ cutTimeString(timeslot.start) }} Uhr |
                    {{ cutTimeString(timeslot.end) }} Uhr
                </option>
            </select>
        </div>
        <div
            class="mt-3 space-y-3 overflow-y-scroll"
            style="height: calc(100vh - 350px)"
        >
            <draggable
                v-model="enrolledUsers"
                group="enrolled"
                item-key="userID"
                class="flex flex-col space-y-3 w-full h-full"
                @change="updateTimeslotStudentMap"
            >
                <template #item="{ element }">
                    <EnrolledListComponent :user="element" />
                </template>
            </draggable>
        </div>
    </div>
</template>

Parent:

<script lang="ts">
import { type Enrollment } from "../stores/enrollment";
import { type User } from "../stores/user";
import EnrolledListComponent from "../Components/EnrolledListComponent.vue";
import Toggle from "../Components/Toggle.vue";
import { Link, router } from "@inertiajs/vue3";
import EnrollmentInformationHeader from "@/Components/EnrollmentInformationHeader.vue";
import axios from "axios";
import EnrollmentEnrolledTableComponent from "@/Components/EnrollmentEnrolledTableComponent.vue";
import { formatEnrollment } from "@/services/EnrollmentServices";

export default {
    name: "EinschreibungErgebnisse",
    components: {
        Link,
        EnrollmentInformationHeader,
        Toggle,
        EnrollmentEnrolledTableComponent,
    },
    props: ["courseEnrollment", "timeSlotReceivers"],
    data() {
        return {
            enrollment: {} as Enrollment,
            enrollmentStatus: "timeLeft" as string | "timeUp" | "finished",
            loadingCorrect: true as boolean,
            timeslotStudentMap: new Map() as Map<number, User[]>,
            isEnrollmentVisible: false as boolean,
            isToggleDisabled: false as boolean,
            studentAlreadyInCourse: false as boolean,
        };
    },
};
</script>

<template>
    <div
      v-if="enrollmentStatus === 'finished'"
      class="w-full flex justify-around mt-2"
    >
       <EnrollmentEnrolledTableComponent
          :enrollment="enrollment"
          :timeslotStudentMap="timeslotStudentMap"
          :isRight="false"
          @update:timeslotStudentMap="
            (value) => (timeslotStudentMap = value)
          "
       />
          <EnrollmentEnrolledTableComponent
            :enrollment="enrollment"
            :timeslotStudentMap="timeslotStudentMap"
            :isRight="true"
            @update:timeslotStudentMap="
               (value) => (timeslotStudentMap = value)
            "
          />
       </div>
</template> 

The problem is that I only have access to item.added or item.removed in the childs component updateTimeslotStudentMap function one at a time. So if one component has added the other has removed and i havent found a way to check if it already existed in both instances.

I already tried to emit an event and pass that to the other component, but i didnt really figure out how to use this.

0

Browse other questions tagged or ask your own question.