Search code examples
javascripthtmlvuejs3vue-componentcomposable

Access to a function in another component in Vue3 with composition API


How can i access to a function in Parent Component from a chield component? I want to click a button in chield component, which should call a function which is in the Parent component.

I have a Headline.vue component which has a click() methode calles LoadLogin:

<template>
  <div>
    <header>
      <h2>my-travel</h2>
      <div @click="navStatus" id="hamburger" class="hamburger-icon-container">
        <span class="hamburger-icon"></span>
      </div>
      <nav id="menue">
        <ul>
          <li @click="homeMenue" ><a href="#home">Home</a></li>
          <li @click="loadLogin"><a href="#Login">Login</a></li>
          <li><a href="#about">about</a></li>
        </ul>
      </nav>
    </header>
  </div>  
</template>

<!-- ############################################################-->


<script setup>

const homeMenue = () => {
  console.log("Home")
}

const navStatus = () => {
  if (document.body.classList.contains('hamburger-active')) {
    document.body.classList.remove('hamburger-active');   
    document.getElementById("menue").classList.remove("closeMenue");
 } 
  else {
    console.log("open");
    document.getElementById("menue").classList.add("closeMenue");
    document.body.classList.add('hamburger-active');
 }
}
</script>

My Parent Component App.vue has a function called loadLogin():

<template> 
  <div>
    <HeadLine/>
    <hr/>      
    <div class="content">
      <LoginUser class="login"/>
    <ContentPicture class="contentPicture"/>
    </div>
  </div>
</template>

<script setup>

import HeadLine from '@/components/HeadLine.vue'
import ContentPicture from '@/components/ContentPicture.vue'
import LoginUser from '@/components/LoginUser.vue'

const loadLogin = () => {

    console.log("Login");
    const element = document.querySelector('.login');
    element.style.display = 'flex';
}

</script>

<style>

body, hr {
  margin: 0em;
}

.content {
  position: absolute;
  top: 60px;
  margin: 1em;
  z-index: -100;
}

.login {
display: none
}

</style>


Solution

  • This is most commonly handled by emitting an event from the child and listening to it on the parent. It's described here in the Vue documentation.

    Child component:

    <li @click="$emit('login')"><a href="#Login">Login</a></li>
    

    Parent component (I assume the child component is <HeadLine />):

    <HeadLine @login="loadLogin" />
    

    On a side note, there are very few situations you need to use the document interface with Vue, which I see you're doing a lot of (querySelector, getElement, classList, etc.). I recommend thoroughly reading the Vue docs to learn how to take full advantage of the framework to do what you want, as the documentation is quite good!