Home > Net >  How to pass data into child component, display in input field, and subsequently be able to submit th
How to pass data into child component, display in input field, and subsequently be able to submit th

Time:12-15

I am still learning Vuejs and I would really appreciate some help!
This is part of my parent component (a table with iterated workshops in each row). The workshop data is fetched from the db using Vuex.
EditWorkshop is my child component. I have a button in each row that I can click such that it opens the modal (child component) with information (about the one specific workshop in that particular row) passed from the parent component to the child component through the use of props, and it is called "workshopItem" in the child component.

<tr v-for="item in workshop" :key="item.id">
    <td>{{ item.title }}</td>
    <td>{{ item.description }}</td>
    <td>{{ item.venue }}</td>
    <td><button @click="openEdit(item)">Edit</button></td>
    <EditWorkshop :workshopItem="modalData" v-show="editVisible" @close="closeEdit"/>
</tr>

<script>
import { mapGetters, mapActions } from 'vuex';
import EditWorkshop from './EditWorkshop.vue'

export default {
    data() {
        return {
            editVisible: false,
            modalData: null,
        }
    },
    components: {
        EditWorkshop
    },
    computed: {
        ...mapGetters(['workshop'])
    },
    methods: {
        ...mapActions(['getWorkshop']),
        openEdit(item) {
            this.modalData = item;
            this.editVisible = true;
        },
        closeEdit() {
            this.editVisible = false;
        }
    },
    created() {
        this.getWorkshop()
    }
}
</script>

This is my child component:

Title: <input type="text" v-model="title">
Description: <input type="textarea" v-model="description">
Venue: <input type="text" v-model="venue">

export default {
    data() {
        return {
            title: '',
            description: '',
            venue: ''
        }
    },
    props: ['workshopItem'],
    methods: {
        close() {
            this.$emit('close')
        }
    },
    mounted() {
        if (this.workshopItem) {
            this.title = this.workshopItem.title
            this.description = this.workshopItem.description
            this.venue = this.workshopItem.venue
        }
    }
}

My problem is: I want to have the input fields display the workshopItem's properties, and I can do that if I do one-way binding :value="workshopItem.title" in the input field. However, I also want to edit the input field and be able to submit the form, and subsequently send the data to the server, therefore only two-way binding is able to work, hence the use of v-model. As seen in the code, I tried using mounted() and it is not able to work (this.workshopItem is null). I also used beforeUpdate() and it is able to display the text value in the input field, but when I tried to edit the input field, I am unable to do so. I am lost and I would appreciate some pointers on what I should do to get the result I want.

CodePudding user response:

First:

if (this.workshop) {

is not defined anywhere, nor in props, nor in data, so it will be undefined.

Then, for the patter you'd like to have, the best solution would be to use computed properties with getter and setter. Take a look here:

https://vuejs.org/v2/guide/computed.html#Computed-Setter

CodePudding user response:

Your problem here is that your modal component had already been rendered and the computed and created hooks are only triggered once. To solve this, every time a the prop changes workShopItem and then create a separate method to initialize your child component's properties once that prop changed

props: ['workShopImte'],

methods: {
    initialize() {
        if (this.workshop) {
            this.title = this.workshopItem.title
            this.description = this.workshopItem.description
            this.venue = this.workshopItem.venue
        }
    }
},

watch: {
    workShopItem: {
        handle() {
            this.initialize()
        },
        immediate: true
    }
}

This way every time the prop changed, your child component's property will get updated accordingly.

Cheers!

  • Related