How to pass props to <nuxt /> component pages
Asked Answered
R

7

10

Has anyone been able to pass props to pages in Nuxt.js?

Typical Vue.js props can be passed as so:

parent-component.vue

<template>
  <child-component :basket-count="items.length"/>
</template>

<script>
import ChildComponent from './child-component'
export default {
  data () {
    items: [{}, {}]
  },
  components: {
    childComponent: ChildComponent
  }
}
</script>

child-component.vue

<template>
  <p>You have {{ basketCount }} items in your basket</p>
</template>

<script>
export default {
  props: [
    'basket-count'
  ]
}
</script>

But when using the <nuxt /> tag in a layout default.vue, props do not get passed to the children pages as they should.

Discussion has taken place already here, but the ticket appears to have no conclusion. I cannot yet troubleshoot a working means of achieving this.

Will post back, but curious to know thoughts from Nuxt.js devs on this?

Rigorous answered 11/6, 2018 at 14:8 Comment(0)
T
9

you have to use camelCase in JavaScript part

<script>
export default {
  props: [
    'basketCount'
  ]
}
</script>

To pass data between components of page, another way is to use a Vuex Store https://nuxtjs.org/guide/vuex-store/

Tressa answered 11/6, 2018 at 17:7 Comment(2)
I do create a nuxtjs aplication using nuxtjs axios module and at pages/index.php i am able to get the data at a stores variable. How can i get the stores variable at the component created at components/stores.vue ?Pericranium
i use async await : async asyncData ({$axios}) { let stores = await $axios.$get('/stores') return {stores} }Pericranium
S
5

Use NuxtChild or router-view

Just Use NuxtChild instead of Nuxt and you can directly pass everything to the pages/compnents that are loaded. Docs

so in layout do something like this


  <div id="app">
    <Header />
    <SocialMedia />
    <main>
      <NuxtChild :myPropNameHere="prop data here" />
    </main>
    <Aside />
  </div>


or like this

so in layout do something like this


  <div id="app">
    <Header />
    <SocialMedia />
    <main>
      <router-view :myPropNameHere="prop data here" />
    </main>
    <Aside />
  </div>


Note : I have noticed that NuxtChild and Nuxt are working slower than router-view in my case, but using router-view might cause some Nuxt features to not work, so it's up to you to decide what to use.

Sibelius answered 11/9, 2021 at 2:36 Comment(2)
Worked for me easiest solution imo. But what is the difference what kind of problems can i expect now that i use NuxtChild instead of Nuxt?Keri
But NuxtChild is working much slower on changes of link that is one problem that I am facingSibelius
P
4

Use custom Vue components with slots.

Here's an example of my Default.vue component:

<template>
  <!-- 
    Note: This is not a typical Nuxt template
    It is just a custom vue component with a slot (https://v2.vuejs.org/v2/guide/components-slots.html)
    I prefer components with slots over Nuxt's layouts becaise custom components are more versatile"
      - they support passing of props
      - they can be chained (you can make nested layouts)
  -->
  <div>
   <!-- custom navbar component which will appear on every page -->
    <Navbar />

    <main>
      <!-- not all pages have a back button -->
      <BackButton v-if="backLink" :backLink="backLink" />

      <!-- page does not have to have a title -->
      <h1 v-if="title">{{ title }}</h1>

      <!-- not all pages have date displays (only posts do) -->
      <div v-if="date" class="date">
        Date added:
        <b>{{ dateDisplay }}</b>
      </div>
      
     <!-- All the content is filled here -->
      <slot></slot>
    </main>
  </div>
</template>

<script>
export default {
  props: {
    title: {
      type: String,
      required: false,
    },
    backLink: {
      type: String,
      required: false,
    },
    date: {
      type: String,
      required: false,
    }
  }
}
</script>

Then in index.vue (or any other page), I can use it like this:

<template>
  <Default title="Index page">
    This is my website's index page. I can put any HTML over here.
  </Default>
</template>

All you have to do is import Default.vue as a vue component.

A little off-topic, but you can use nuxt/components. This way, you don't have to import and register a Vue component on every single page.

Advantages of this method:

  • Props can be passed
  • These can be used anywhere, in any page. This means they can be chained (nested). For example you can have a Root parent layout, with a BlogPost child layout, where BlogPost "inherits" from Root.
Procrustes answered 27/5, 2020 at 4:13 Comment(2)
Thanks for taking the time to answer, I believe this is arguably the best solution- encapsulating props within a component as opposed to the root nuxt element. I just thought at the time it would be more DRY and less repetition for certain elements. But having a layout component I now feel makes logical sense.Rigorous
May I know what solution you used before? I used the vuex method as shown in the other answer, but that felt really "hacky" and got pretty messyProcrustes
G
0

You have to use this in child-component.vue:

<script>
export default {
    props: {
        basketCount: {
            type: Number,
            default: 0
        }
    }
</script>
Guilty answered 4/10, 2020 at 17:43 Comment(0)
E
0

I have the same issue. According to the thread below it's not possible to pass props to a element:

https://github.com/nuxt/nuxt.js/issues/1502

Equipotential answered 15/7, 2021 at 18:33 Comment(0)
C
0

Overall, if you want to pass some state in Vue, you need to use the props down/emit up pattern.

If you don't have a simple way of passing some state up to a direct parent, the simplest solution is still to use Vuex (that and not an Event Bus btw).
Even if there are hacky ways to achieve it, I do not recommend it in terms of readability + complexity for you and your team.

Christian answered 12/5, 2022 at 13:37 Comment(0)
T
0

Nuxt 2

It's not very well documented, or implied, but, it works, the exact same way as it does in Vue, since its a Vue framework ;)

Parent:

<template>
  <div>
    <child-component :prop="{ message: `text`}" />
  </div>
</template>

Child:

<template>
  <div>{{ prop }}</div><!-- will output : { message: `text`} -->
</template>
<script>
export default {
  props: {
    prop: {
      default: () => {}, // must be a function
      type: Object, // String, Array, Object, Number etc.
    },
  },
};
</script>
Towery answered 9/8, 2023 at 9:26 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.