Categories
Quasar

Developing Vue Apps with the Quasar Library — Table No Data Display and Custom Sorting

Spread the love

Quasar is a popular Vue UI library for developing good looking Vue apps.

In this article, we’ll take a look at how to create Vue apps with the Quasar UI library.

No Data Display

We can display something when no data is displayed in our table.

For instance, we can write:

<!DOCTYPE html>
<html>
  <head>
    <link
      href="https://fonts.googleapis.com/css?family=Roboto:100,300,400,500,700,900|Material+Icons"
      rel="stylesheet"
      type="text/css"
    />
    <link
      href="https://cdn.jsdelivr.net/npm/quasar@1.12.13/dist/quasar.min.css"
      rel="stylesheet"
      type="text/css"
    />
  </head>
  <body class="body--dark">
    <script src="https://cdn.jsdelivr.net/npm/vue@^2.0.0/dist/vue.min.js"></script>
    <script src="https://cdn.jsdelivr.net/npm/quasar@1.12.13/dist/quasar.umd.min.js"></script>
    <div id="q-app">
      <q-layout
        view="lHh Lpr lFf"
        container
        style="height: 100vh;"
        class="shadow-2 rounded-borders"
      >
        <div class="q-pa-md">
          <q-table
            title="Treats"
            :data="data"
            :columns="columns"
            :filter="filter"
            no-data-label="I didn't find anything for you"
            no-results-label="The filter didn't uncover any results"
            row-key="name"
          >
            <template v-slot:top-right>
              <q-input
                borderless
                dense
                debounce="300"
                v-model="filter"
                placeholder="Search"
              >
                <q-icon slot="append" name="search"></q-icon>
              </q-input>
            </template>

            <template v-slot:no-data="{ icon, message, filter }">
              <div>No data</div>
            </template>
          </q-table>
        </div>
      </q-layout>
    </div>
    <script>
      const columns = [
        {
          name: "name",
          required: true,
          label: "Dessert",
          align: "left",
          field: (row) => row.name,
          format: (val) => `${val}`,
          sortable: true
        },
        {
          name: "calories",
          align: "center",
          label: "Calories",
          field: "calories",
          sortable: true
        },
        { name: "fat", label: "Fat (g)", field: "fat", sortable: true },
        {
          name: "calcium",
          label: "Calcium (%)",
          field: "calcium",
          sortable: true,
          sort: (a, b) => parseInt(a, 10) - parseInt(b, 10)
        }
      ];
      const data = [
        {
          name: "Frozen Yogurt",
          calories: 159,
          fat: 6.0,
          calcium: "14%"
        },
        {
          name: "Ice cream sandwich",
          calories: 237,
          fat: 9.0,
          calcium: "8%"
        },
        {
          name: "Eclair",
          calories: 262,
          fat: 16.0,
          calcium: "6%"
        },
        {
          name: "Honeycomb",
          calories: 408,
          fat: 3.2,
          calcium: "0%"
        },
        {
          name: "Donut",
          calories: 452,
          fat: 25.0,
          calcium: "2%"
        },
        {
          name: "KitKat",
          calories: 518,
          fat: 26.0,
          calcium: "12%"
        }
      ];
      new Vue({
        el: "#q-app",
        data: {
          columns,
          data,
          filter: ""
        }
      });
    </script>
  </body>
</html>

to add that.

We populate the no-data slot with the content we want to show when there’s no data displayed in the table.

Hide Bottom Bar

We can hide the bottom bar by adding the hide-bottom prop:

<!DOCTYPE html>
<html>
  <head>
    <link
      href="https://fonts.googleapis.com/css?family=Roboto:100,300,400,500,700,900|Material+Icons"
      rel="stylesheet"
      type="text/css"
    />
    <link
      href="https://cdn.jsdelivr.net/npm/quasar@1.12.13/dist/quasar.min.css"
      rel="stylesheet"
      type="text/css"
    />
  </head>
  <body class="body--dark">
    <script src="https://cdn.jsdelivr.net/npm/vue@^2.0.0/dist/vue.min.js"></script>
    <script src="https://cdn.jsdelivr.net/npm/quasar@1.12.13/dist/quasar.umd.min.js"></script>
    <div id="q-app">
      <q-layout
        view="lHh Lpr lFf"
        container
        style="height: 100vh;"
        class="shadow-2 rounded-borders"
      >
        <div class="q-pa-md">
          <q-table
            title="Treats"
            :data="data"
            :columns="columns"
            row-key="name"
            hide-bottom
          >
          </q-table>
        </div>
      </q-layout>
    </div>
    <script>
      const columns = [
        {
          name: "name",
          required: true,
          label: "Dessert",
          align: "left",
          field: (row) => row.name,
          format: (val) => `${val}`,
          sortable: true
        },
        {
          name: "calories",
          align: "center",
          label: "Calories",
          field: "calories",
          sortable: true
        },
        { name: "fat", label: "Fat (g)", field: "fat", sortable: true },
        {
          name: "calcium",
          label: "Calcium (%)",
          field: "calcium",
          sortable: true,
          sort: (a, b) => parseInt(a, 10) - parseInt(b, 10)
        }
      ];
      const data = [
        {
          name: "Frozen Yogurt",
          calories: 159,
          fat: 6.0,
          calcium: "14%"
        },
        {
          name: "Ice cream sandwich",
          calories: 237,
          fat: 9.0,
          calcium: "8%"
        },
        {
          name: "Eclair",
          calories: 262,
          fat: 16.0,
          calcium: "6%"
        },
        {
          name: "Honeycomb",
          calories: 408,
          fat: 3.2,
          calcium: "0%"
        },
        {
          name: "Donut",
          calories: 452,
          fat: 25.0,
          calcium: "2%"
        },
        {
          name: "KitKat",
          calories: 518,
          fat: 26.0,
          calcium: "12%"
        }
      ];
      new Vue({
        el: "#q-app",
        data: {
          columns,
          data,
          filter: ""
        }
      });
    </script>
  </body>
</html>

Custom Sorting

We can add custom sorting by setting the sort-method prop to our own sorting method:

<!DOCTYPE html>
<html>
  <head>
    <link
      href="https://fonts.googleapis.com/css?family=Roboto:100,300,400,500,700,900|Material+Icons"
      rel="stylesheet"
      type="text/css"
    />
    <link
      href="https://cdn.jsdelivr.net/npm/quasar@1.12.13/dist/quasar.min.css"
      rel="stylesheet"
      type="text/css"
    />
  </head>
  <body class="body--dark">
    <script src="https://cdn.jsdelivr.net/npm/vue@^2.0.0/dist/vue.min.js"></script>
    <script src="https://cdn.jsdelivr.net/npm/quasar@1.12.13/dist/quasar.umd.min.js"></script>
    <div id="q-app">
      <q-layout
        view="lHh Lpr lFf"
        container
        style="height: 100vh;"
        class="shadow-2 rounded-borders"
      >
        <div class="q-pa-md">
          <q-table
            title="Treats"
            :data="data"
            :columns="columns"
            row-key="name"
            :sort-method="customSort"
            binary-state-sort
          >
          </q-table>
        </div>
      </q-layout>
    </div>
    <script>
      const columns = [
        {
          name: "name",
          required: true,
          label: "Dessert",
          align: "left",
          field: (row) => row.name,
          format: (val) => `${val}`,
          sortable: true
        },
        {
          name: "calories",
          align: "center",
          label: "Calories",
          field: "calories",
          sortable: true
        },
        { name: "fat", label: "Fat (g)", field: "fat", sortable: true },
        {
          name: "calcium",
          label: "Calcium (%)",
          field: "calcium",
          sortable: true,
          sort: (a, b) => parseInt(a, 10) - parseInt(b, 10)
        }
      ];
      const data = [
        {
          name: "Frozen Yogurt",
          calories: 159,
          fat: 6.0,
          calcium: "14%"
        },
        {
          name: "Ice cream sandwich",
          calories: 237,
          fat: 9.0,
          calcium: "8%"
        },
        {
          name: "Eclair",
          calories: 262,
          fat: 16.0,
          calcium: "6%"
        },
        {
          name: "Honeycomb",
          calories: 408,
          fat: 3.2,
          calcium: "0%"
        },
        {
          name: "Donut",
          calories: 452,
          fat: 25.0,
          calcium: "2%"
        },
        {
          name: "KitKat",
          calories: 518,
          fat: 26.0,
          calcium: "12%"
        }
      ];
      new Vue({
        el: "#q-app",
        data: {
          columns,
          data
        },
        methods: {
          customSort(rows, sortBy, descending) {
            const data = [...rows];

            if (sortBy) {
              data.sort((a, b) => {
                const x = descending ? b : a;
                const y = descending ? a : b;

                if (sortBy === "name") {
                  return x[sortBy] > y[sortBy]
                    ? 1
                    : x[sortBy] < y[sortBy]
                    ? -1
                    : 0;
                } else {
                  return +x[sortBy] - +y[sortBy];
                }
              });
            }

            return data;
          }
        }
      });
    </script>
  </body>
</html>

The customSort method takes the rows parameter which has all the table data.

sortBy has the field that we sort by.

And descending is a boolean that indicates whether we sort in descending order or not.

Conclusion

We can add custom sorting and no data display into our Quasar table.

By John Au-Yeung

Web developer specializing in React, Vue, and front end development.

Leave a Reply

Your email address will not be published. Required fields are marked *