Vue-good-table: How to do actions buttons with a custom vue event using htmlContent prop?

Created on 30 Jun 2017  路  10Comments  路  Source: xaksis/vue-good-table

First of all. Nice job so far you all are doing very well with this component. This is the easiest vue table component to implement I found on the internet and it meets at least my requirements.

I saw the td templating option with something like this

<template slot="table-row" scope="props">
    <td>{{ props.row.name }}</td>
    <td>{{ props.row.age }}</td>
    <td>{{ props.row.btn }}</td>
  </template>

This template works perfectly and it gives you full content manipulation. However is I define this template optionI would need to rewrite all rows td. But now..
How about defining the template in the htmlContent Prop on the columns definitions?

<vue-good-table title="Users"
                            :columns="[
                            { label:'Customer ID', field:'CustomerID' },
                            { label:'Name', field:'Name' },
                            { label:'Email', field:'Email' },
                            { label:'Account Number', field:'AccountNumber' },
                            { label:'Primary Phone', field:'PrimaryPhone' },
                            { label:'Postal Address', field:'PostalAddress' },
                             //Something like this
                            { label:'Actions', field:'ID', html:true, htmlContent:'<button v-on:click=\'delete(props.row.ID)\'>Delete</button>' }
                            ]"
                            :rows="rows"
                            :paginate="true"
                            :line-numbers="true"
                            style-class="table table-bordered table-striped condensed" />

I tried this but its only display the ID value rather than the button instead... I also need a value passed down to the event. Any working example?

Thanks in advance!

Most helpful comment

My bad. Thank you very much!

All 10 comments

hmm I was reading the source I found something weird in here

<tbody>
        <tr v-for="(row, index) in paginated" :class="onClick ? 'clickable' : ''" @click="click(row, index)">
          <th v-if="lineNumbers" class="line-numbers">{{ getCurrentIndex(index) }}</th>
          <slot name="table-row" :row="row">
            <td v-for="(column, i) in columns" :class="getDataStyle(i)">
              <span v-if="!column.html">{{ collectFormatted(row, column) }}</span>
              <span v-if="column.html" v-html="collect(row, column.field)"></span>
            </td>
          </slot>
        </tr>
      </tbody>

I think this should be if !column.html then display the field?

v-if="!column.html" v-html="collect(row, column.field)"

cause if html is false when want the column.field with format if specified

if html is true then return the htmlContent?

I don't see the htmlContent prop anywhere in the source...
I think something is not right here or its missing...

<vue-good-table title="Users"
                            :columns="[
                            { label:'Customer ID', field:'CustomerID' },
                            { label:'Name', field:'Name' },
                            { label:'Email', field:'Email' },
                            { label:'Account Number', field:'AccountNumber' },
                            { label:'Primary Phone', field:'PrimaryPhone' },
                            { label:'Postal Address', field:'PostalAddress' },
                            { label:'Actions', html:true, htmlContent:'<button>Delete</button>' }
                            ]"
                            :rows="rows"
                            :paginate="true"
                            :line-numbers="true"
                            style-class="table table-bordered table-striped condensed">
                <template slot="table-row" scope="props">
                    <td>{{ props.row.CustomerID }}</td>
                    <td>{{ props.row.Name }}</td>
                    <td>{{ props.row.Email }}</td>
                    <td>{{ props.row.AccountNumber }}</td>
                    <td>{{ props.row.PrimaryPhone }}</td>
                    <td>{{ props.row.PostalAddress }}</td>
                    <td><button :id="props.row.ID" v-on:click="click(props.row.ID)">Delete</button></td>
                </template>
            </vue-good-table>

This work perfect but I would still like to go with the other approach cause is more cleaner and concise...
Like this...
{ label:'Actions', field:'ID', html:true, htmlContent:'<button :id=\'props.row.ID\' v-on:click=\'click(props.row.ID)\'>Delete</button>' }

@arivera12 thank you for spending some time understanding the component. The problem with what you are suggesting is that the component will then need to take your html string and somehow restore the binding + variables that you're using within your html string. This isn't currently supported by vue. If you wanted static html then sure you could specify html:true in the column (as indicated in the readme) and then specifying the html string in the respective row:

For example, if your column definition was:

[
      { label:'Customer ID', field:'CustomerID' },
      { label:'Name', field:'Name' },
      { label:'Email', field:'Email' },
      { label:'Account Number', field:'AccountNumber' },
       { label:'Primary Phone', field:'PrimaryPhone' },
       { label:'Postal Address', field:'PostalAddress' },
      { label:'Actions', field: 'actions', html:true }
]

your rows should then have:

rows: [
    {  
        CustomerID: //...,
        // other properties
       'actions': '<span class=\'some-class\'>Blah</span>'
    }
]

The best way to maintain the vue bindings etc is using the dynamic template as you're already doing currently. If you think of a better way, I'd be happy to review a pull request!

Ok I see. The problem with the bindings... Well I could still do some server side stuff for this I think. Thanks!

@xaksis could you give a more comprehensive example? I'm trying to replicate @arivera12 last example, unsuccessfully :(

@amravazzi what are you trying to do? Maybe open a new issue and post your code so I can take a look?

Thanks @xaksis! I just figured out what I was doing wrong.

So, I kept writing my code as so:

<template slot="table-row" scope="props">
  <td><img src="{{ props.row.imageLink }}"/></td>
  <td>{{ props.row.productName }}</td>
  <td>{{ props.row.productCode }}</td>
  <td>{{ props.row.salePrice }}</td>
</template>

It throws the error:
src="{{ props.row.imageLink }}": Interpolation inside attributes has been removed. Use v-bind or the colon shorthand instead. For example, instead of <div id="{{ val }}">, use <div :id="val">

Then I change to
... <img :src="{{ props.row.imageLink }}"/> ... or ... <img v-bind:src="{{ props.row.imageLink }}"/> ...
as it's said.

Then this throws another error:
Module build failed: SyntaxError: Unexpected token

What am I doing wrong? Or this binding is not supported? Is there any other way to achieve this? imageLink comes from the row vector and is set on the column vector too. I'm using Vue.js 2.2.2 and Vue-good-table 1.10.0.

Thanks in advance.

this is unrelated to vue-good-table. You're binding your values incorrectly:
change: <img :src="{{ props.row.imageLink }}"/>
to: <img :src="props.row.imageLink"/>

you should go over the vuejs documentation... it will help you sort some of these things out.
relevant doc: https://vuejs.org/v2/guide/syntax.html#Attributes

My bad. Thank you very much!

Was this page helpful?
0 / 5 - 0 ratings

Related issues

sylvaincaillot picture sylvaincaillot  路  3Comments

advicepyro picture advicepyro  路  3Comments

unixconky picture unixconky  路  4Comments

enghelewa picture enghelewa  路  3Comments

mgd722 picture mgd722  路  7Comments