Be part of JetBrains PHPverse 2026 on June 9 – a free online event bringing PHP devs worldwide together.

Aetrox's avatar

dynamic table

Hello,

i build a little data-table to output different data with one vue-component. the problem is, the object keys are not the same for each table. There are always 2 columns but it can be "ID, Name" or "Extension, Name".

I tried for 2 days but couldnt find a solution to use prop-values as object keys in v-for. this is what it actually looks:

<template>
    <div style="overflow: auto; height: 500px;">
        <table class="table">
            <thead>
                <tr><th class="w-25" v-for="field in fields">{{field}}</th></tr>
            </thead>
            <tbody>
                <tr v-for="item in data"><td class="w-25">{{item.id}}</td><td>{{item.id}}   </td></tr>
            </tbody>
        </table>
    </div>
</template>

<script>

export default {
    props: ['data','fields']
}


</script>

I would need something like item.field[0] and item field[1], but i didnt knew how to get this working. Is it possible or has someone a hint how to get this working?

Thanks in Advance.

Simon

0 likes
7 replies
jrdavidson's avatar

You could assign a type of an empty array to the fields prop then pass in the array of fields that you need to loop through in your vue template.

matquest's avatar

So I pass an array of objects to my "columns" prop (what you're calling fields) and then I can pass additional options/functions for each column to the table:

columns: [
    {
        heading: 'Image',
    },
    {
        heading: 'Number',
        filter: '',
        value: row => row.number,
    }
],

and a separate table rows prop (what you're calling data)

note: each row should v-for the rows prop on the TR tag, then you should v-for on the TD tag for columns (yes, even for the data rows!)

I output the row data in one of two ways, first I check to see if value was defined for the current column (see number column above), if so I use that value function like this:

<template v-if="column.value">
         {{ column.value(row) }}
 </template>

that works well for simple fields, if I want to decorate the field or do more with it, I use a named template between the opening and closing custom table tags like this:

<template
    slot="image"
    slot-scope="props"
>
        <img
          title="thumbnail"
          :src="props.row.photos_by_width[100][0].temp_url"
          style="height: 50px"
        />
</template>

and this gets outputted from the table component with something like this:

<slot
        v-else
        :name="slotName(column)"
        :row="row"
        :rowI="rowI"
/>

That slot name is simply a camelCased version of the column heading, which is how I name all the templates used for this purpose.

I threw a lot out there so please ask questions if you need more clarification.

Aetrox's avatar

Thanks for your answers.

Its pretty hard for me to wrap my head around your answer because i have not that much vue knowledge.

I lately realized that i dont use vues feature of reusing components.

Now i wanted to clean my code and tried to build reusable templates.

So you say, you pass

Columns = [{column 1 details},{column 2 details}]

and

Rows = [{Data 1},{Data2}]

each Data has multiple object-values like id, name, extension, updated and so on.

In your Columns array you have the column heading but what is the value?

Could you explain it more detailed for me? ^^`

thank you very much.

matquest's avatar

If the row cell is just going to have a simple value in it, a string or a number, I just define the value on the column object as a function that outputs the correct property from the row. So for example, if the rows consist of objects that have a name defined ie:

{
  name: 'John',
}

and I want a column with the name, then the column object for that will look like

{
    heading: 'Name', //used in your th table heading
    value: row => row.name, // this is an arrow function that outputs the 'name' value of the row given to it
}

so in your table component, you'd v-for the columns in the heading row and use column.heading for the th and then you'd v-for the rows for your body table rows and v-for columns for each cell, in the cell that's where you'd say something like this,

<template v-if="column.value">
  {{ column.value(row) }}
</template>

there you're checking to see if value was defined on the column and if so, assuming it's a function and passing the row to it (assuming because you designed it that way)

if all of your table cells will output simple data like that, skip the v-if and just define the value on each column, I use named templates with slots for some cells that require formatting or other components to be loaded into them as I described above but it doesn't sound like you need that, I hope this helps, good luck with your table component!

Aetrox's avatar

Thanks for your explanation. I think i got what you did.

You assign each heading a value that you double loop at the tr/td to get each item of the data objects in the array of objects.

My problem i think lies at the data i try to display, my object has updated and created at, name, extension, id as well as a pivot and i cant get it to only id and name and extension and name. So at the moment i have problems how to extract only the id or the extension and the name in one object to v-for it.

Not sure if i maybe missunderstood something.

matquest's avatar
matquest
Best Answer
Level 8

So your row objects can have a bunch of fields, it's that value function you define in the column object that pulls the correct one:

columns = [
  {
    heading: 'Id', 
    value: row => row.id
  },
  {
    heading: 'Name',
    value: row => row.name
  }
]

It's admittedly a kinda tough thing to wrap your head around but it makes for a pretty sweet re-usable table component when you get it set up, I'd show you my table but there's a lot more going on with it that would make it harder to digest... I think you should probably go back through all the vue related videos on here, it will pay off in the long run, I watched them all a few times before I started building my components.

Aetrox's avatar

Thank you @matquest,

Yes i thought that this would be the point. Yeah i should watch every video, i normally try to play with what i learned until i get it and then switch to the next video.

I understand what you do and its really cool.

Wow had this first part written 6 hours before and know i come back to thank you! Wanted to write that i cant get what you do but ... its super smart and i got how you did it.

I have stopped counting how often i read your example to find out what you did to get this working.

Thank you very much @matquest. :)

^^ couldnt get it working the first 4 hours because i deletet the ">" from the last of the component -.-`

1 like

Please or to participate in this conversation.