0

I am using Vue-CLI. I have a Vue component which is called viewGenres.vue. This component contains Vuetify table which presents all of the current genres from Vue store. I am trying to add a new option for each genre which is "Edit".

My objective is that for each line in the table there will be an edit button. Once the button is clicked, a new component called editGenre.vue should be rendered.

This component should contain a filled-out form with all the existing details of the specific genre. I have several questions:

1) Once I click on the edit button, the following exception appears on browser:

ReferenceError: Vue is not defined at VueComponent.editGenre

2) In order for me to load the right properties from the DB, I need to define the "ID" prop of the editGenre component. Does anyone have any recommendation on the best method to do so?

This is viewGenres.vue: (the method editGenre is the one responsible for rendering the new component).

<template>
    <div class="root" ref="container">
        <h2>Genres Info</h2>
        <br>
        <v-data-table
            :headers="headers"
            :items="genres"
            hide-actions
            class="elevation-1">
            <template slot="items" slot-scope="props">
                <td class="text-xs-left">{{ props.item.id }}</td>
                <td class="text-xs-left">{{ props.item.name }}</td>
                <td class="text-xs-left">{{ props.item.desc }}</td>
                <td class="text-xs-left">{{ props.item.artists }}</td>
            <td class="text-xs-left"><v-btn flat @click="editGenre(props.item.id)">EDIT</v-btn></td>
                <td class="text-xs-left"><v-btn flat @click="deleteGenre(props.item.id)">Delete</v-btn></td>
            </template>
        </v-data-table> 
    </div>
</template>
<script>
import editGenre from '@/components/administratorView/Genres/editGenre.vue'
const firebase = require('../../../firebaseConfig.js')

export default {
    data: function(){
        return{
            headers: [
            { text: 'ID', value: 'id'},
            { text: 'Name', value: 'name'},
            { text: 'Description', value: 'desc'},
            { text: 'Artists', value: 'artists'},
      { text: 'Edit Genre'},
            { text: 'Delete From DB'}
            ]
        }
    },
    computed: {
    genres: function(){
      return this.$store.state.genre.genres
    }
    },
  components: {
    editGenre
  },
    methods: {
    editGenre: function(id){
      var ComponentClass = Vue.extend(editGenre)
      var instance = new ComponentClass()
      instance.$mount()
      this.$refs.container.appendChild(instance.$el)
    },
        deleteGenre: function(id){
            console.log("Trying to delete " +id)
            firebase.firestore.collection("genres").doc(id).delete().then(()=>{
            this.$store.dispatch('genre/getGenresFromDB')
                alert("Deleted Document Successfully")
            }).catch(function(error){
                alert(error)
            })
        }
    },
  mounted(){
    this.$store.dispatch('genre/getGenresFromDB')
  }
}
</script>
<style scoped>
</style>

This is editGenre.vue:

<template>
    <v-dialog v-model="editGenre" persistent max-width="500px">
        <v-card>
            <v-card-title>
                <h2>Edit Genre {{genre.name}}</h2>
            </v-card-title>
            <v-card-text>
                <v-text-field
                        v-model="name"
                        label="Name"
                        :error-messages="nameErrors"
                        @touch="$v.name.$touch()"
                        @blur="$v.name.$touch()"
                />
                <v-textarea
                        v-model="desc"
                        label="Description"
                        box
                />
                <v-combobox
                    v-model="artists"
                    label="Artists"
                    :items="artistNames"
                    :error-messages="artistsErrors"
                    @touch="$v.artists.$touch()"
                    @blur="$v.artists.$touch()"
                    multiple>
                </v-combobox>
                <v-btn
                        color="primary"
                        @click="submit">
                        Submit
                </v-btn>
                <v-btn
                    color="primary"
                    @click="close">
                    Close
                </v-btn>
            </v-card-text>          
        </v-card>   
    </v-dialog>
</template>
<script>
import { required } from 'vuelidate/lib/validators'
const firebase = require('../../../firebaseConfig')

export default{
    data: function(){
        return{
            name: '',
            desc: '',
            artists: []
        }
    },
    props: {
        id: String
    },
    mounted: function(){
        let docRef = firebase.firestore.collection("genres").doc(this.id)
        docRef.get().then(function(doc){
            if(doc.exists){
                this.name = doc.data().name
                this.desc = doc.data().desc
                this.artists = doc.data().artists
            }
            else{
                console.error("Doc Doesn't Exist!")
            }
        }).catch(function(error){
            console.error(error)
        })
    }
}
</script>
<style scoped>
</style>

Thank You! Tom

0

1 Answer 1

2

You missed to import Vue in your viewGenres.vue component, so add it as follow :

   ....
   <script>
      import Vue from 'vue'
      import editGenre from '@/components/administratorView/Genres/editGenre.vue'
       const firebase = require('../../../firebaseConfig.js')
      ....

You could pass props by this way :

      var ComponentClass = Vue.extend(
              props:{
                id:{type:String, default () { return id}}
               },editGenre)

and remove this :

     props: {
       id: String
    }

according to Evan You :

It's not recommended to use new to manually construct child components. It is imperative and hard to maintain. You probably want to make your child components data-driven, using and v-for to dynamically render child components instead of constructing them yourself.

Sign up to request clarification or add additional context in comments.

2 Comments

Thank you it solved my first question! Do you have any suggestions for my second question?
@TomHarpaz you're welcome, i edited my answer i hope it would help you

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.