Vue.js - Issue with Data Communication between Two Components using $emit

38 views Asked by At

Description: I am facing an issue with data communication between two Vue.js components - DashboardHome and StatusPage.vue. I am using $emit to send data from the DashboardHome component, but it seems like the data is not being received by the StatusPage.vue component. I would appreciate any insights or assistance in identifying and resolving this problem.

Issue Details:

The DashboardHome component emits the "setup-local" event with the heartBeatList data.

The StatusPage.vue component has a method handleEvent that should receive the emitted data.

Code: Below are the relevant portions of the code for both components:

DashboardHome.vue

<!-- DashboardHome.vue -->
<template>
    {{ this.$root.importantHeartbeatList }}
    <transition ref="tableContainer" name="slide-fade" appear>
            <div class="shadow-box table-shadow-box" style="overflow-x: hidden;">
                <table class="table table-borderless table-hover">
                    <thead>
                        <tr>
                            <th>{{ $t("Name") }}</th>
                            <th>{{ $t("Status") }}</th>
                            <th>{{ $t("DateTime") }}</th>
                            <th>{{ $t("Message") }}</th>
                        </tr>
                    </thead>
                    <tbody>
                        <tr v-for="(beat, index) in displayedRecords" :key="index"
                            :class="{ 'shadow-box': $root.windowWidth <= 550 }">
                            <td><router-link :to="`/dashboard/${beat.monitorID}`">{{ beat.name }}</router-link></td>
                            <td>
                                <Status :status="beat.status" />
                            </td>
                            <td :class="{ 'border-0': !beat.msg }">
                                <Datetime :value="beat.time" />
                            </td>
                            <td class="border-0">{{ beat.msg }}</td>
                        </tr>

                        <tr v-if="importantHeartBeatList.length === 0">
                            <td colspan="4">
                                {{ $t("No important events") }}
                            </td>
                        </tr>
                    </tbody>
                </table>

                <div class="d-flex justify-content-center kuma_pagination">
                    <pagination v-model="page" :records="importantHeartBeatList.length" :per-page="perPage"
                        :options="paginationConfig" />
                </div>
            </div>
        </div>
    </transition>
    <router-view ref="child" />
</template>

<script>
import Status from "../components/Status.vue";
import Datetime from "../components/Datetime.vue";
import Pagination from "v-pagination-3";

export default {
    components: {
        Datetime,
        Status,
        Pagination,
    },
    props: {
        calculatedHeight: {
            type: Number,
            default: 0
        }
    },
    data() {
        return {
            page: 1,
            perPage: 25,
            initialPerPage: 25,
            heartBeatList: [],
            paginationConfig: {
                hideCount: true,
                chunksNavigation: "scroll",
            },
        };
    },
    computed: {

        importantHeartBeatList() {
            let result = [];

            for (let monitorID in this.$root.importantHeartbeatList) {
                let list = this.$root.importantHeartbeatList[monitorID];
                result = result.concat(list);
            }

            for (let beat of result) {
                let monitor = this.$root.monitorList[beat.monitorID];

                if (monitor) {
                    beat.name = monitor.name;
                }
            }

            result.sort((a, b) => {
                if (a.time > b.time) {
                    return -1;
                }

                if (a.time < b.time) {
                    return 1;
                }

                return 0;
            });

            // eslint-disable-next-line vue/no-side-effects-in-computed-properties
            this.heartBeatList = result;

            return result;
        },

        displayedRecords() {
            const startIndex = this.perPage * (this.page - 1);
            const endIndex = startIndex + this.perPage;
            return this.heartBeatList.slice(startIndex, endIndex);
        },
    },
    watch: {
        importantHeartBeatList() {
            this.$nextTick(() => {
                this.updatePerPage();
            });
        },
        heartBeatList: {
            handler(newVal, oldVal) {
                this.$nextTick(() => {
                    console.log("new val", newVal);
                    this.$emit("setup-local", newVal)
                    console.log("sent", newVal);
                });
            }
        }
    },
    mounted() {
        this.initialPerPage = this.perPage;

        window.addEventListener("resize", this.updatePerPage);
        this.updatePerPage();
    },
    beforeUnmount() {
        window.removeEventListener("resize", this.updatePerPage);
    },
    methods: {
        updatePerPage() {
            const tableContainer = this.$refs.tableContainer;
            const tableContainerHeight = tableContainer.offsetHeight;
            const availableHeight = window.innerHeight - tableContainerHeight;
            const additionalPerPage = Math.floor(availableHeight / 58);

            if (additionalPerPage > 0) {
                this.perPage = Math.max(this.initialPerPage, this.perPage + additionalPerPage);
            } else {
                this.perPage = this.initialPerPage;
            }

        },
    },
};
</script>

StatusPage.vue

<!-- StatusPage.vue -->
<template>
    <DashboardHome @setup-local="handleEvent" />
</template>

<script>
import DashboardHome from "./DashboardHome.vue";

export default {

    components: {
        DashboardHome,
    },

    data() {
        return {
        };
    },
    methods: {
        handleEvent(newVal) {
            console.log("recieved", newVal);
        },
    }
}
</script>

Output for DashboardHome's console: In the console it is showing that the data was sent. I have console logged the before sent of $emit and after the $emit

Output for StatusPage's console: Here the data was not recieved by the DashboardHome component, but in the dashboard component's console it is showing that the data was sent.

Observations:

  • I have confirmed that the data is being emitted from DashboardHome using console.log.

  • However, the handleEvent method in StatusPage.vue does not seem to be receiving the emitted data.

What I've Tried:

  • Checked the order of lifecycle hooks to ensure the components are mounted before emitting events.

  • Examined the watchers and $nextTick usage for potential issues.

Question: What could be causing the emitted data not to be received in the StatusPage.vue component? Are there any common pitfalls or mistakes I might be overlooking?

Any assistance or suggestions would be greatly appreciated. Thank you!

0

There are 0 answers