Home > database >  Can't seem to pass data to component via props in Vue
Can't seem to pass data to component via props in Vue

Time:09-22

I'm making a dynamic table using Vue 3 as a learning project, in which the user can add or remove rows from the table, among other things. I'm using a table-row component to create the row, and a table-data component to create data cells within that row. Adding a row is done via the following code:

const app = Vue.createApp({
    data() {
        return {
            tableRows: [],
        }
    },

    methods: {
        addRow() {
            this.tableRows.push(-1);
        },
    },
})

What I need to do is to pass the array TableRows and index to the table-row component, in order to perform a row delete operation, as shown in this code:

app.component('table-row', {
    props: {
        tableRows: Array,
        index: Number,
    },

    methods: {
        deleteRow(index) {
            this.tableRows.splice(index, 1);
        }
    },

    template: `
        <tr>
            <table-data></table-data>
            <table-data></table-data>
            <table-data></table-data>
            <table-data></table-data>
            <button @click="deleteRow">Delete Row</button>
        </tr>
    `
})

The issue is that both the values of TableRows and index are undefined (as seen in the Vue DevTools), which means the props are not being passed from the parent to the child component. I think that's the reason why this error pops up whenever I click the Delete Row button:

Uncaught TypeError: Cannot read properties of undefined (reading 'splice')

Here's a screenshot from Vue DevTools. You can see that the props variables have undefined values:

Vue DevTools screenshot

I'm not really sure why is this happening, or what I can do to remedy this. Any help is greatly appreciated.

CodePudding user response:

I think all props must first be declared in the parent's data before they're bound as props in children

"PARENT"
<template>
...
  <Child :tableRows="tableRows" />
...
</template>

...
<script>
 ...
  data() {
    return {
      tableRows: []
    }
  }
  ...
</script>
"CHILD"
...
</script>
  ...
  props: {
    tableRows: Array
  }
  ...
</script>

As for index, you will likely have to emit the event back up to the parent on click.

"CHILD"
<template>
...
  <button @click="$emit('deleteRow')">Delete Row</button>
...
</template>

Here you'd have to deal with it in the parent, where e is the value associated with the event--in this case, presumably the index you want.

"PARENT"
<template>
...
  <Child @deleteRow="deleteRow(e)" :tableRows="tableRows" />
...
</template>

CodePudding user response:

You didn't pass index in @click="deleteRow" Try to change method to :

deleteRow() {
   this.tableRows.splice(this.index, 1);
}

or pass index to method:

@click="deleteRow(index)"
  • Related