I'm working on creating a table component using Vuejs. The app uses laravel as the backend along with inertiajs. I have a resource that is returned for displaying a resource. In the resource I am trying to add some data that I don't want displayed, these will be links to edit and delete the resource. I also may have to add an ID for having a checkbox on each row of the table as well.
My question is how can I exclude the links and meta from being displayed in the loop of data but then show them as a checkbox or link? It's been a long day I hope this is clear.
PermissionResource
public function toArray($request)
{
return [
'name' => $this->name,
'links' => [
'edit' => action([PermissionController::class, 'edit'], $this),
'delete' => action([PermissionController::class, 'destroy'], $this),
],
'meta' => [
'id' => $this->id
]
];
}
Table.vue
<script setup>
import { computed, ref } from 'vue';
const props = defineProps({
data: {
type: Object,
required: true
}
});
const hasActionLinks = ref(props.data.filter((item) => item.hasOwnProperty('links')));
const hasRowSelector = ref(props.data.filter((item) => item.hasOwnProperty('meta')));
</script>
<template>
<div>
<table>
<thead>
<tr>
<th v-if="hasRowSelector" scope="col">
<input id="selectAll" type="checkbox" v-model="selectAll" />
</th>
<th v-for="(heading, index) in Object.keys(data[0]).map((heading) => heading.replace(/_/g, ' '))" v-bind:key="index" scope="col">
{{ heading }}
</th>
<th v-if="hasActionLinks" scope="col">
Actions
</th>
</tr>
</thead>
<tbody>
<tr v-for="(row, index) in Object.values(data)" :key="index">
<td v-if="hasRowSelector">
<input type="checkbox" v-model="selected" :value="row.meta.id" />
</td>
<td v-for="(value, myindex) in Object.values(row)" v-bind:key="myindex">
{{ value }}
</td>
<td v-if="hasActionLinks">
// EDIT AND DELETE LINKS HERE
</td>
</tr>
</tbody>
</table>
</div>
</template>
You could change your v-for="(value, myindex) in Object.values(row)"
to ignore the property "links" and "meta". This could be done using either a function, or a computed value.
<script>
const unwantedColumns = ref(['links', 'meta']);
const getFilterableProps = (row) => {
return Object.values(row).filter(col => !unwantedColumns.value.includes(col));
}
</script>
And then use this function in your template
<tbody>
<tr v-for="(row, index) in Object.values(data)" :key="index">
<! -- ... -->
<td v-for="(value, myindex) in getFilterableProps(row)" v-bind:key="myindex">
<! -- ... -->
</td>
<! -- ... -->
</tr>
</tbody>
A more efficient way to do this would be to declare a "columns" array that contains all the columns you want to show and iterate through that, rather than attempting to dynamically defines the columns.
<script>
const columns = ref([
'property1',
'property2',
...
])
</script>
<template>
<!-- ... -->
<td v-for="(column, myindex) in columns" v-bind:key="myindex">
{{ row[column] }}
</td>
<!-- ... -->
</template>
Anyways, I hope this gave you some ideas on how to fix the issue. Please note that the provided code is UNTESTED and should be used as reference only.