Nuxt.js: Access current page object within layout

Created on 28 Mar 2017  Â·  24Comments  Â·  Source: nuxt/nuxt.js

For example to show current page title in layout

This question is available on Nuxt.js community (#c402)

Most helpful comment

  head () {
    let sefl = this
    if (process.browser) {
      this.title = document.title
    }
    return {
      changed ({title}) {
        sefl.title = title
      }
    }
  },

All 24 comments

@Darkside73 I haven't tested it but what if you add a ref on nuxt component in layout (<nuxt ref=page>) And trying to access it with this.$refs.page? (It will not be available in data only after mounted())

It's available only in mounted hook but without data:

Page

export default {
  data () {
    return {
      title: 'Page Title'
    }
  }
}

Layout

<template>
  <!-- TypeError: Cannot read property 'title' of undefined -->
  <div>{{$refs.page.title}}</div>
</template>
<script>
export default {
  mounted () {
    console.log(this.$refs.page.title) // undefined
  }
}
</script>

What about console.log(this.$refs.page.componentInstance.title) ? :))

No success
TypeError: Cannot read property 'title' of undefined

For data access problem :

<template>
  <div>{{pageTitle}}</div>
</template>
<script>
export default {
 data() {
  return { pageTitle: '' }
 }
  mounted () {
   const page  = this.$refs.page.componentInstance;
   this.pageTitle=page.title;
  }
}
</script>

Can you inspect what exactly this.$refs.page.componentInstance is using console? I think there is an component inside it

Also if you see (https://github.com/nuxt/nuxt.js/blob/master/lib/app/components/nuxt.vue#L17) It seems there are many other ways accessing <nuxt> element.

this.$refs.page.nuxtChild may also help :)) (Brute forcing Nuxt :D)

Both this.$refs.page.componentInstance and this.$refs.page.nuxtChild give me undefined.
And this.$nuxt.$refs.page.title as well.
Only this.$nuxt.$children[0].title shows desired results

I wanna ask if you can catch title you want on mounted function , is SSR will get desired results and print to source html ?
thanks .

Yes. Works on server side as well

On Tue, Mar 28, 2017, 20:22 羅 常瑋 notifications@github.com wrote:

I wanna ask if you can catch title you want on mounted function , is SSR
will get desired results and print to source html ?
thanks .

—
You are receiving this because you were mentioned.
Reply to this email directly, view it on GitHub
https://github.com/nuxt/nuxt.js/issues/464#issuecomment-289842247, or mute
the thread
https://github.com/notifications/unsubscribe-auth/AAUujAh4Q1Gkp2MiMN-7SHteE9KsBxQqks5rqUG9gaJpZM4Mrz58
.

This approach does not work if route changes: this.$nuxt.$children[0] never changes on client-side navigation
@alexchopin could you please reopen the issue

Maybe you can just listen to route changes and update current child :

import router from '~router'


  router.afterEach((from, to)=>{ 
    // 
  }

How I can get actual child component?

Just was an idea, but inside afterEach function we have access to this and we can get new value on route change events

It doesn't work. Even if use watch, child still points to prev component:

watch: {
  $route () {
    this.title = this.$nuxt.$children[0].title // outdated title
  }
}

I've accomplish it via vuex:

store/index.js

export const state = {
  pageTitle: 'Default Title'
}

export const mutations = {
  SET_PAGE_TITLE (state, title) {
    state.pageTitle = title
  }
}

layouts/default.vue

<template>
  <h1>{{$store.state.pageTitle}}</h1>
</template>

pages/index.vue

<template>
  <div></div>
</template>

<script>
export default {
  asyncData ({ req }) {
    return {
      title: `Main Page ${req ? 'server' : 'client'}`
    }
  },
  head () {
    return {
      title: this.title
    }
  },
  mounted () {
    this.$store.commit('SET_PAGE_TITLE', this.title)
  }
}
</script>

But looking for more concise approach though

I am also looking for a more concise approach than @Darkside73 last comment. This is the only thing I can get to work currently.

Thanks for sharing the 'mounted+store' solution. I'm using a mixin to save typing; although I haven't tried the mixin with a 'head' attribute.

export let storeTitle = (title) => ({
  mounted () {
    this.$store.commit('SET_PAGE_TITLE', title)
  },
  destroyed () {
    this.$store.commit('SET_PAGE_TITLE', 'Default Title')
  }
})

  head () {
    let sefl = this
    if (process.browser) {
      this.title = document.title
    }
    return {
      changed ({title}) {
        sefl.title = title
      }
    }
  },

For title i use computed property:

title() {
  return this.$meta().inject().titleChunk;
}
  head () {
    let sefl = this
    if (process.browser) {
      this.title = document.title
    }
    return {
      changed ({title}) {
        sefl.title = title
      }
    }
  },

This is what worked for me...and it's pretty clean, too. Thank you!

The this.$meta().inject().titleChunk almost worked for me but the title was sometimes outdated (held the previous page's title).

Indeed, @chrisleyva, that solved the problem for me as well. That is the best solution I think.

This thread has been automatically locked since there has not been any recent activity after it was closed. Please open a new issue for related bugs.

Was this page helpful?
0 / 5 - 0 ratings

Related issues

vadimsg picture vadimsg  Â·  3Comments

danieloprado picture danieloprado  Â·  3Comments

surmon-china picture surmon-china  Â·  3Comments

vadimsg picture vadimsg  Â·  3Comments

lazycrazy picture lazycrazy  Â·  3Comments