最新消息:雨落星辰是一个专注网站SEO优化、网站SEO诊断、搜索引擎研究、网络营销推广、网站策划运营及站长类的自媒体原创博客

javascript - How can I loop through API resource data but exclude certain properties based on the key when displaying on the fro

programmeradmin6浏览0评论

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>

This is the current result

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>

This is the current result

Share Improve this question asked Mar 12 at 16:45 Danny ConnollyDanny Connolly 9013 gold badges10 silver badges31 bronze badges 2
  • It makes more sense to prepare data you iterate to fit presentation better instead of writing js in a template. For dynamic reactive data use computeds – Estus Flask Commented Mar 12 at 18:41
  • @EstusFlask Thanks for your comment. So would you suggest having the resource return a showable key along with links and meta and then put the columns I want to show in the showable array? – Danny Connolly Commented Mar 12 at 21:30
Add a comment  | 

1 Answer 1

Reset to default 0

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.

与本文相关的文章

发布评论

评论列表(0)

  1. 暂无评论