Question:
How to solve the inconsistent VueJS props when passing from parent to child?

Problem

I'm trying to pass down a prop from the parent component to the child component, but it seems like the child cannot get the prop correctly.

This is the parent component:


<template>

  <div>

    <b-table striped hover :items="items" :fields="fields">

      <template #cell(actions)="row">

        <b-button

          size="sm"

          @click="openModal(row.item, row.index, $event.target)"

          class="mr-1"

        >

          Sua

        </b-button>

        <b-button size="sm" @click="row.toggleDetails" variant="danger">

          Xoa

        </b-button>

      </template>


      <template #row-details="row">

        <b-card>

          <ul>

            <li v-for="(value, key) in row.item" :key="key">

              {{ key }}: {{ value }}

            </li>

          </ul>

        </b-card>

      </template>

    </b-table>

    <item-update-modal

      ref="itemUpdateModal"

      :id="modalAttributes.id"

      :title="modalAttributes.title"

      :propItem="propItem"

    />

  </div>

</template>


<script>

import ItemInfoModal from "@/components/item/ItemInfoModal.vue";


export default {

  name: "ItemList",

  components: {

    "item-update-modal": ItemInfoModal,

  },

  props: {

    items: [],

  },

  data() {

    return {

      showModal: false, // Initially, the modal is hidden

      fields: [

        {

          key: "id",

          label: "Ma so",

          sortable: true,

          sortDirection: "desc",

          class: "text-center",

        },

        {

          key: "name",

          label: "Ten san pham",

          sortable: true,

          sortDirection: "desc",

        },

        {

          key: "description",

          label: "Mo ta",

          sortable: true,

        },

        {

          key: "specification",

          label: "Quy cach",

          sortable: true,

        },

        {

          key: "itemUnit",

          label: "Don vi",

          sortable: true,

          class: "text-center",

        },

        { key: "actions", label: "Chi tiet" },

      ],

      modalAttributes: {

        id: "itemUpdateModal",

        title: "Sua ban thanh pham",

      },

      propItem: {},

    };

  },

  methods: {

    openModal(item, index, button) {

      // Show the modal when the button is clicked

      this.propItem = JSON.parse(JSON.stringify(item));

      this.$root.$emit(

        "bv::show::modal",

        this.modalAttributes.id,

        button

      );

    },

    resetInfoModal() {

      this.modalAttributes.propItem = {};

    },

    onFiltered(filteredItems) {

      // Trigger pagination to update the number of buttons/pages due to filtering

      this.totalRows = filteredItems.length;

      this.currentPage = 1;

    },

  },

};

</script>


And my child component is:

<template>

  <div>

    <b-modal

      :id="id"

      v-model="showModal"

      centered

      :title="title"

      @ok="onSubmit"

      @show="openModal"

    >

      <b-form @reset="onReset">

        <b-form-group

          id="input-group-item-name"

          label="Ten san pham"

          label-for="input-item-name"

        >

          <b-form-input

            id="input-item-name"

            v-model="item.name"

            type="text"

            required

          ></b-form-input>

        </b-form-group>

        <b-form-group

          id="input-group-item-description"

          label="Mo ta san pham"

          label-for="input-item-description"

        >

          <b-form-input

            id="input-item-description"

            v-model="item.description"

            type="text"

            required

          ></b-form-input>

        </b-form-group>

        <b-form-group

          id="input-group-item-unit"

          label="Don vi"

          label-for="item-unit"

        >

          <b-form-select

            id="item-unit"

            v-model="item.itemUnit"

            :options="itemUnitOptions"

          ></b-form-select>

        </b-form-group>

        <b-form-group

          id="input-group-item-specification"

          label="Quy cach"

          label-for="input-item-specification"

        >

          <b-form-textarea

            id="input-item-specification"

            v-model="item.specification"

            type="text"

            rows="4"

            required

          ></b-form-textarea>

        </b-form-group>

      </b-form>

    </b-modal>

  </div>

</template>


<script>

import itemApi from "@/api/items";

export default {

  name: "ItemInfoModal",

  data() {

    return {

      showModal: false,

      item: { ...this.propItem },

      itemUnitOptions: [

        { value: "EA", text: "EA" },

        { value: "GR", text: "GR" },

      ],

    };

  },

  props: {

    id: {

      type: String,

      required: true,

    },

    title: {

      type: String,

      required: true,

    },

    propItem: { type: Object, required: false, default: () => {} },

  },

  methods: {

    openModal() {

      console.log(this.propItem);

      this.showModal = true;

    },

    closeModal() {

      this.showModal = false;

    },

    onSubmit(event) {

      event.preventDefault();

      if (this.item.id) {

        console.log("updating");

        itemApi.updateItem(this.item);

      } else {

        console.log("creating");

        itemApi.createItem(this.item);

      }

      this.$router.go(0);

    },

    onReset(event) {

      event.preventDefault();

      console.log(this.item);

      // Reset the updatedItem object

      this.item = {};

    },

  },

};

</script>


This is the UI:


I'm trying to fill the form with the content of the selected row item, but somehow it's not working. I tried to log the props, but the first time when I hit the gray button, I got "{ob: Observer}", then I closed the modal and opened the modal again, this time I got my "propItem", but the form still not filled as expected.


Update: I copied my project to this: >https://codesandbox.io/p/sandbox/vue3-371lz2

Please help. Many thanks!


Solution

In your child component, instead of data item try to use computed property, like


computed: { 

  item() {

    return {...this.record}

  }

}



I think the child component just assigns an empty value to ur data item prop and can't update it. I hope it will help!


Suggested blog

>Create a project using Vue.js: Beginners Guide

>Authentication with Vue 3 and Firebase

>Plugins and Presets for Vuejs project

>Create a Vue.js application with CLI Services

>Create a project using Vue.js: Beginners Guide

>Create Vue.js application API


Nisha Patel

Nisha Patel

Submit
0 Answers