Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How Do I Pass Props Using Single File Components?

Coming to Vue from React. For the most part there are a lot of similarities but passing props seems a little different. I couldn't find much documentation on how to do this using single file components. I import all my data for the app in main.js. I'm wondering how I can get parts of my data like currentUser for example, to ResourceInfo.vue? Again assuming these are all single file components. Do I need to pass it down through the <App/> part under main.js template option, then into <resource-info></resource-info> in App.vue then somehow into ResourceInfo.vue? I'd like to stay away from having to learn Vuex as well because I'm just starting out. Thanks!

main.js

import Vue from 'vue'
import App from './App'
import ResourceInfo from '../src/components/ResourceInfo'
var db = firebase.database();
var auth = firebase.auth();

/* eslint-disable no-new */
var vm = new Vue({
  el: '#app',
  data: function() {
    return {
        users: {},
        currentUser: {},
        quizzes: {},
        resources: []
    }
  },
  template: '<App/>',
  components: { App, ResourceInfo },
})

App.vue

<template>
  <div id="app">
    <navbar></navbar>
    <resource-info></resource-info>
  </div>
</template>

<script>
import Navbar from './components/Navbar'
import ResourceInfo from './components/ResourceInfo'

export default {
  name: 'app',
  components: {
    Navbar,
    ResourceInfo
  }
}
</script>

<style>
</style>

ResourceInfo.vue

<template>
</template>

<script>
var resourcesRef = firebase.database().ref('resources');

module.exports = {
  name: 'resource-info',
  data: function() {
    return {
      header: 'Before you build your quiz we just need some quick info.',
      resource: {
        type: '',
        title: '',
        url: '',
        desc: '',
        timesPassed: 0
      },
    }
  },
  firebase: {
    resources: resourcesRef
  },
  methods: {
    saveToFirebase: function() {
      resources.push({
        resource: this.resource
      })

      // Clear inputs  

      this.resource.title = '',
      this.resource.type = '',
      this.resource.desc = '',
      this.resource.url = ''

      console.log("Saving resource data...")

    }
  }
}
</script>

<style>
</style>
like image 867
maxwellgover Avatar asked Dec 07 '22 20:12

maxwellgover


1 Answers

@DanM. has already provided the answer, and I hope you managed to fix your props as per his guidance.

I am writing this answer so I can share my method of dealing with currentUser in my app (only for logged-in users). Here is my project structure (highly simplified for this answer):

Template: webpack, installed using vue init webpack my-project using vue-cli

My app files:

  • ./main.js: app entry file
  • ./App.vue: responsible for page layout, like header, footer, and route contents using router-view
  • ./components/: Common components like navbar, footer, etc.
  • ./routes/: Route components. I prefer to put it here instead of cluttering my components folder.
  • and a lot more...

Code in my main.js: Just the standard code to define routes and bootstrap the app. Nothing special here.

Code in my App.vue - here is where currentUser gets fetched. Navbar also gets inserted, where I pass currentUser via props

<template>
    <div class="app-container">
        <app-navbar :currentUser="currentUserInfo"></app-navbar>
        <router-view></router-view>
        <app-footer></app-footer>
    </div>
</template>
<script>
import AppNavbar from "./components/app-navbar.vue"
import AppFooter from "./components/app-footer.vue"

export default {
    components: {
        "app-navbar": AppNavbar
    },
    data: function() {
        return {
            currentUserInfo: {
                loading: true
            } // start with an empty object and modify later
        }
    },
    // ... all other code ...
    created: function() {
        // Ensure that this is a logged-in user. Or else redirect to login page
        this.$http.get("/api/currentUser").then(response => {
            // process response
            this.currentUserInfo = response
            this.currentUserInfo.loading = false
        }, error => {
            // user not found. exit the Vue app and go to login page (directly from server)
            // Refer to my other answer: http://stackoverflow.com/a/40194152/654825

            // Or alternatively, you can serve your App's index.html only for logged-in users. Then you will never reach here.
        })
    },
    // ... more code ...
}
</script>

Now receive currentUser in your component ./components/navbar.vue as follows:

<template>
    <div class="navbar">
        <!-- some code - branding, etc.. -->
        <div>{{currentUser.loading ? "Loading..." : currentUser.name}}</div>
        <!-- some more code - logout link, etc.. -->
    </div>
</template>
<script>
export default {
    props: ["currentUser"],
    // and more ...
}
</script>

Thats a lot to digest. I also use vuex extensively, which I did not show in the sample above as you did not want vuex.

I hope it helps to structure your app.

like image 106
Mani Avatar answered Dec 11 '22 09:12

Mani