How do I get a parent and child vue components to share data with another?

Since my guestbook webapp has a sign component and a view component, I feel the need to not put all code into one component.

But question two is how do I get one data object from one script to the next?

I’ve tried the following:

/src/components/Guestbook.vue

<template>
<div>
    <h1>Guestbook</h1>

    <SignGuestbook />
    <ViewGuestbook :entries="v_entries" />
    <ViewGuestbook :p_entries="v_entries" />
    <!-- Error: '[Vue warn]: Property or method "store" is not defined on the instance but referenced during render.' -->
    <!-- <ViewGuestbook :entries="store" /> -->
    <!--   <ViewGuestbook :p_entries="store" /> -->
    <!-- Error: '[Vue warn]: Property or method "$store" is not defined on the instance but referenced during render.' -->
    <!-- <ViewGuestbook :entries="$store" /> -->
    <!-- <ViewGuestbook :p_entries="$store" /> -->
</div>
</template>

<script>
import SignGuestbook from './SignGuestbook.vue'
import ViewGuestbook from './ViewGuestbook.vue'
import Vue from 'vue'
import Vuex from 'vuex'
import guestbook from './guestbook.js'

Vue.use(Vuex)

const store = new Vuex.Store({
  state: {
    entries: [
      { id: 1, name: 'stored 1', comment: 'comment' },
      { id: 2, name: 'stored 2', comment: 'comment' }
    ]
  },
  getters: {
    entries: entries => {
      return entries
    }
  },
  mutations: {
    refreshList (state) {
      state.s_entries = guestbook.getItems()
    }
  }
})

export default {
  name: 'Guestbook',
  components: {
    SignGuestbook,
    ViewGuestbook
  },
  props: ['v_entries'],
  data () {
    return { comment: '', name: '', entries: ['test'] }
  },
  methods: {
    refreshList: async function () {
      this.entries = await guestbook.getItems()
      store.commit('refreshList')
      // this.$store = await guestbook.getItems()
      console.log('regular entries:', this.entries)
      console.log('stored entries:', this.store.getters.entries)
    }
  },
  async created () {
    await guestbook.authoriseAndConnect()
    await guestbook.createMutableData()
    await this.refreshList()
  }
}
</script>

/src/components/ViewGuestbook.vue

<template>
  <div>

    get entries attempt #1<br>
    <div v-for="entry in entries">
      an entry<br>
    </div>
    <br>
    get entries attempt #2<br>
    {{ entries }}
    <br>
    <!-- Error: '[Vue warn]: Property or method "$store" is not defined on the instance but referenced during render.' -->
    <!-- stored entries<br>
    {{ this.$store }}
    <br>-->
    <br>

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

<script>

export default {
  name: 'ViewGuestbook',
  props: ['p_entries'],
  data () {
    return { entries: [
      { id: 1, name: 'child 1', comment: 'comment' },
      { id: 2, name: 'child 2', comment: 'comment' }
    ] }
  },
  async created () {
    this.entries = this.p_entries
  }
}

</script>

/src/components/guestbook.js

let app
let md

async function authoriseAndConnect () {
  const opts = {
    forceUseMock: true
  }
  let appInfo = {
    name: 'SAFE Guestbook Application',
    id: 'net.maidsafe.tutorials.web-app',
    version: '0.1.0',
    vendor: 'MaidSafe.net Ltd.'
  }
  app = await window.safe.initialiseApp(appInfo, null, opts)
  console.log('Authorising SAFE application...')
  try {
    const authReqUri = await app.auth.genAuthUri()
    console.log('Generated authentication URI...', authReqUri)
    const authUri = await window.safe.authorise(authReqUri)
    console.log('SAFE application authorised...')
    await app.auth.loginFromUri(authUri)
  } catch (err) {
    console.warn('Application authorisation was rejected', err)
  }
  console.log('Application connected to the network')
}

async function createMutableData () {
  console.log('Creating MutableData with initial dataset...')
  const typeTag = 15000
  md = await app.mutableData.newRandomPublic(typeTag)
  const initialData = {
    'random_key_1': JSON.stringify({
      name: 'parent 1',
      comment: 'comment'
    }),
    'random_key_2': JSON.stringify({
      name: 'parent 2',
      comment: 'comment'
    })
  }
  await md.quickSetup(initialData)
}

async function getItems () {
  const entries = await md.getEntries()
  let entriesList = await entries.listEntries()
  let items = []
  entriesList.forEach((entry) => {
    const value = entry.value
    if (value.buf.length === 0) return
    const parsedValue = JSON.parse(value.buf)
    items.push({ key: entry.key, value: parsedValue, version: value.version })
  })
  return items
}

module.exports = {
  authoriseAndConnect,
  createMutableData,
  getItems
}

index.js

import Vue from 'vue'
import App from './App'
import router from './router'

export default new Vue({
  el: '#root',
  router,
  render: (h) => h(App)
})

// Error: unused variable
// let globalData = new Vue({
//   data: {
//     $store: {}
//   }
// })

// Error: '[Vue warn]: Property or method "$store" is not defined on the instance but referenced during render.'
// Vue.mixin({
//   computed: {
//     $store: {
//       get: function () { return globalData.$data.$store },
//       set: function (newData) { globalData.$data.$store = newData }
//     }
//   }
// })

Expected (at least one of them):

get entries attempt #1
an entry
an entry
get entries attempt #2
[{ id: 1, name: 'stored 1', comment: 'comment' },{ id: 2, name: 'stored 2', comment: 'comment' }]

Result:

get entries attempt #1

get entries attempt #2

i m not a skilled man in codage but i try to learn .good work go on

As this question is not really specific to SAFE I would suggest looking for other resources that help you with your problem.


Anyway, some remarks:

  • You’re using require as well as import/export. I think that’s confusing as you would usually only need one of those mechanisms.
  • It might be that the error lies in the circular way the app is built. Guestbook includes ViewGuestbook which includes Guestbook again.
  • Why not include the guestbook.js directly from the ViewGuestbook.vue?
  • Look into https://vuex.vuejs.org/ . I think your problem arises from a design point of view. Think about how you’re structuring your app.

I’ve updated the problem.

Your update changed the question completely. The core issue is still unrelated to SAFE.

Passing data is perfectly explained in the Vue.js guide: https://vuejs.org/v2/guide/components.html#Passing-Data-to-Child-Components-with-Props


I would be glad to help you via Riot; I don’t think this is forum material.

1 Like

@bzee Thanks for helping me out.

Though I still stand by that the vuejs guide is rather minimal and obtuse due to the fact that one has to make a
“translation switch” from Global component code to Single File Component code.

Here is the solution:

/src/components/Guestbook.vue

<template>
<div>
    <h1>Guestbook</h1>

    <SignGuestbook />
    <ViewGuestbook v-bind:entries="d_entries" />
</div>
</template>

<script>
import SignGuestbook from './SignGuestbook.vue'
import ViewGuestbook from './ViewGuestbook.vue'

import guestbook from '~/api/guestbook'

export default {
  name: 'Guestbook',
  components: {
    SignGuestbook,
    ViewGuestbook
  },
  data () {
    return {
      comment: '',
      name: '',
      d_entries: []
    }
  },
  methods: {
    refreshList: async function () {
      this.d_entries = await guestbook.getItems()
    }
  },
  async created () {
    await guestbook.authoriseAndConnect()
    await guestbook.createMutableData()
    await this.refreshList()
  }
}
</script>

/src/components/ViewGuestbook.vue

<template>
  <div>

    entries<br>
    <div v-for="entry in entries">
      {{ entry.value.name }}<br>
      {{ entry.value.comment }}<br>
    </div>

  </div>
</template>

<script>

export default {
  name: 'ViewGuestbook',
  props: {
    'entries': Array
  }
}
</script>

To share data, bind a data object from a parent component to a props object of a child component using v-bind.

1 Like

Glad to be of help so far!

I see a few examples use the Vue.component function, but the only difference is that the template value is put in separate <template> tags in a Single File Component. That shouldn’t make it harder to understand. Actually, the guides being minimalist I’ve found them to be extremely to the point and clear.


I saw Vue.js has a forum; they might be able to help you much quicker with some of these basic Vue.js issues.

1 Like

This topic was automatically closed after 60 days. New replies are no longer allowed.