Topic: Datatable Custom Column Formatting

mkind free asked 3 years ago


How do I provide custom rendering (or formatting) for columns in datatables?

  1. I have to provide buttons with custom actions on the row containing the button
  2. I have to provide custom formatting (e.g. rendering columns containing an array of strings as a collection of pills/badges/...)

Other frameworks provide solutions e.g. using slots, for rendering a checkbox this would look like:

  <v-data-table
    :items="users"
  >
    <template v-slot:item.isActive="{ item }">
      <v-checkbox
        v-model="item.isActive"
        readonly
      />
    </template>
</v-data-table>

and another example for rendering custom action buttons

  <v-data-table>
    <template v-slot:item.action="{ item }">
      <v-icon
        class="mx-1"
        :disabled="!item.permissions.update"
        @click.stop="editUser(item)"
      >
        mdi-pencil
      </v-icon>
      <v-icon
        class="mx-2"
        :disabled="!item.permissions.destroy"
        @click="deleteUser(item)"
      >
        mdi-trash-can-outline
      </v-icon>
    </template>
  </v-data-table>

making the current item available to the template via Vue slots.

How do I implement this using MDB? I checked many other posts for information but couldn't find anything helpful. Thanks in advance for pointing me in the right direction!


Magdalena Dembna staff answered 3 years ago


The only way you can render your custom content is with v-html directive (so it has to be raw HTML, not Vue components):

{ ...row, contact: "<button class='btn btn-primary btn-floating'><i class='fa fa-phone'></i></button>' }

As for formatting, check out the Object structure tag here: https://mdbootstrap.com/docs/vue/tables/datatables/#a-usage You can add an additional field to each column format, for example:

{ ...column, format: value => value.toUpperCase() }

Best regards, Magdalena


mkind free commented 3 years ago

Thanks for your feedback Magdalena. I definitely did miss the format directive in the docs.

So just two follow-up questions regarding my original ones above:

  1. The format only affects the display format, it does not have impact on sorting (e.g. Date values) - is my assumption correct?

  2. When passing in custom content via v-html, how would I provide functionality (e.g. call a routine that opens up an edit dialog for the item of the row containing the button)? As it cannot be a Vue component, how do I add callbacks?

Thanks again & Best regards, Marko


Magdalena Dembna staff commented 3 years ago

  1. It should not have any effect on sorting - it's just the displayed value.
  2. It requires additional code, you can try something like this:

data: {
        columns: [
          {
            label: "Name",
            field: "name",
            sort: true
          },
          {
            label: "Position",
            field: "position",
            sort: true
          },
          {
            label: "Office",
            field: "office",
            sort: true
          },
          {
            label: "Age",
            field: "age",
            sort: true
          },
          {
            label: "Start date",
            field: "date",
            sort: true
          },
          {
            label: "Salary",
            field: "salary",
            sort: false,
            format: value => "£" + value
          },
          {
            label: "Action",
            field: "action",
            sort: false,
          }
        ],
        rows: [
          {
            name: "Tiger Nixon",
            position: "System Architect",
            office: "-",
            age: "61",
            date: "2011/04/25",
            salary: "320",
            action: '<button class="btn btn-floating btn-primary my-action-btn" data-entry="0"><i class="fa fa-phone"></i></button>'
          },
          {
            name: "Garrett Winters",
            position: "Accountant",
            office: "Tokyo",
            age: "63",
            date: "2011/07/25",
            salary: "170",
            action: '<button class="btn btn-floating btn-primary my-action-btn" data-entry="1"><i class="fa fa-phone"></i></button>'
          },
          {
            name: "Ashton Cox",
            position: "Junior Technical Author",
            office: "San Francisco",
            age: "66",
            date: "2009/01/12",
            salary: "86",
            action: '<button class="btn btn-floating btn-primary my-action-btn" data-entry="2"><i class="fa fa-phone"></i></button>'
          },
          {
            name: "Cedric Kelly",
            position: "Senior Javascript Developer",
            office: "Edinburgh",
            age: "22",
            date: "2012/03/29",
            salary: "433",
            action: '<button class="btn btn-floating btn-primary my-action-btn" data-entry="3"><i class="fa fa-phone"></i></button>'
          },
          {
            name: "Airi Satou",
            position: "Accountant",
            office: "Tokyo",
            age: "33",
            date: "2008/11/28",
            salary: "162",
            action: '<button class="btn btn-floating btn-primary my-action-btn" data-entry="4"><i class="fa fa-phone"></i></button>'
          },

methods: {
    addEventListeners() {
      document.getElementsByClassName('my-action-btn').forEach(btn => {
        btn.addEventListener('click', () => {
          const index = btn.getAttribute('data-entry');

          console.log(this.data.rows[index]);
        })
      })
    }
  },
  mounted() {
    this.$nextTick(() => {
      this.addEventListeners();
    })
  }


Please insert min. 20 characters.

FREE CONSULTATION

Hire our experts to build a dedicated project. We'll analyze your business requirements, for free.

Status

Answered

Specification of the issue

  • ForumUser: Free
  • Premium support: No
  • Technology: MDB Vue
  • MDB Version: 6.7.1
  • Device: any
  • Browser: any
  • OS: any
  • Provided sample code: No
  • Provided link: No
Tags