Toggle div in parent component when button is clicked from child component using Composable

Viewed 66

I have 3 pages:

  1. spinner.js - composable. Function to toggle loading spinner
  2. App.vue - parent component
  3. Test.vue - child component

What I need to do is when I click the button from Test.vue, the App.vue should know that the value of loading has been changed and should show/hide the div accordingly.

I tried using watch but I don't really have the total grasp on how to use it. I tried reading the documents but it's still vague for me.

Should I use emit instead for this scenario? But I need to use the composable spinner.js

spinner.js

import { ref } from 'vue'
export default function useSpinner() {
    const loading = ref(false)

    const isLoading = async (isLoading) => {
        loading.value = isLoading
    }

    return {
        loading,
        isLoading,
    }
}

Test.vue

<template>
    <button @click="showSpinner">Show Spinner</button>
</template>

<script>
import useSpinner from "./composables/spinner.js"

export default {
    setup() {
        const { isLoading } = useSpinner()

        // Calls `isLoading()` from `spinner.js` to change the value of `loading`
        const showSpinner = async () => {
            isLoading(true)
        }
        return {
            loading,
            showSpinner,
        }
    },
}
</script>

App.vue

<template>
    <div v-if="loading">Hello Loading Spinner</div>
</template>

<script>
import useSpinner from "./composables/spinner.js"
import { watch } from "vue";

export default {
    setup() {
        const { loading } = useSpinner()

        // should watch when `loading` was changed to toggle div
        watch(loading, (currentValue, oldValue) => {
            console.log(currentValue);
            console.log(oldValue);
        });

        return {
            loading,
        }
    },
}
</script>
1 Answers

const loading = ref(false) needs to be outside the export. example:

import { ref } from 'vue';
const loading = ref(false);
export default function useSpinner() {
    const isLoading = (isLoading) => {
        loading.value = isLoading
    }
    return {
        loading,
        isLoading,
    };
}

If not, both Test.vue and App.vue will have their own instance of loading when you import the loading ref using the function.

Related