JanuszO
JanuszO

Reputation: 1240

vue can't querySelector for child component DOM element

I cannot search for child component DOM element, my settings are as follows:

pages/Login.vue

<template>
 <section class="login">
    <div v-show="step === 4" class="login__container">
      <Test />
    </div>
  </section>
</template>

<script>
export default {
  data () {
    return {
      step: 1
    }
  },
  async mounted () {
      this.step = 4 
      await this.$nextTick()
      document.querySelector('.test') // NULL
  },
}
</script>

components/Test.vue

<template>
  <div class="test">
    foo
  </div>
</template>

setTimeout of course is not solution. I also try the same on other page, but without success. What am I doing wrong? I guess the problem must be somewhere in the template or project configuration

@edit

i tried to do the same effect on jsfiddle vue template and fresh nuxt project but no problem there

Upvotes: 2

Views: 3114

Answers (4)

kissu
kissu

Reputation: 46696

This kind of code should work properly

parent.vue

<template>
  <div>
    <test ref="parentTest" @hook:mounted="selectChildElement"></test>
  </div>
</template>

<script>
export default {
  methods: {
    selectChildElement() {
      console.log(this.$refs.parentTest.$refs.test)
    },
  },
}
</script>

Test.vue component

<template>
  <div ref="test">foo</div>
</template>

This is because of the way the parent and children components are mounted, as explained here: https://stackoverflow.com/a/44319825/8816585


As Brahim said, it is also better to use $refs in an SPA context, more info available here.

The @hook:mounted trick was taken from this answer and initially found in this dev.to post.

Upvotes: 2

JanuszO
JanuszO

Reputation: 1240

As I thought, the problem is with nuxt, namely auto-importing components. I am using automatic component import in the nuxt configuration.

nuxt.config.js

  components: [
    {
      path: '~/components',
      pathPrefix: false,
    },
  ],

This approach apparently breaks something, and only after manually importing the component did it work properly

import Test from '@/components/Test.vue'

export default {
  name: 'LoginPage',
  components: {
    Test
  },

So the nuxt configuration caused the problem. Thank you for all your help.

Upvotes: 0

Batuhan
Batuhan

Reputation: 1611

Another way to access child component is emitting event when its ready and created in DOM,

In the child element:

    <template>
      <div ref="test">foo</div>
    </template>
    <script>
    export default {
      mounted() {
        this.$emit('childMounted', this.$refs.test)
      }
    }
    ...

In your parent:

    <template>
     <section class="login">
        <div v-show="step === 4" class="login__container">
          <Test @childMounted="childMounted"/>
        </div>
      </section>
    </template>
    
    <script>
    export default {
      data () {
        return {
          step: 1
        }
      },
      methods: {
       childMounted(childRef) {
         // Try here 
         // childRef: your child component reference
       }
      }
    }
    </script>

Upvotes: 1

Boussadjra Brahim
Boussadjra Brahim

Reputation: 1

You could try to use ref instead of querySelector to manipulate the component DOM :

<template>
 <section class="login">
    <div v-show="step === 4" class="login__container">
      <Test ref="test"/>
    </div>
  </section>
</template>

<script>
export default {
  data () {
    return {
      step: 1
    }
  },
  mounted () {
      this.step = 4 
   
      let test=this.$refs.test
  },
}
</script>

Upvotes: 0

Related Questions