Categories
JavaScript

Coding Conventions for Writing JavaScript

Like any other programming language, JavaScript has its own programming languages that developers should follow. There’re lots of rules to follow, but there’re some basic ones that affect code in the whole program.

Why We Need JavaScript Coding Conventions?

Having conventions makes things easier to understand since codebases have the same conventions.

Naming and declaration of variables, functions, classes, and other entities are consistent in their naming scheme. This means that we can understand code easier and makes things more predictable.

White space, indentation, and comments makes code easy to read and don’t clutter up the screen.

Also, maintenance is faster since it’s easier to understand and trace. This makes debugging easier.

Variables and Functions

Variable names should be camel case. This also applies to functions.

Names should start with a letter.

For example, the following is good:

let birthDay;

However, the following is not:

let 123birthday;

Classes

Class names start with an upper case letter and the rest are camel case, which is also called Pascal case.

There should be one space before the opening curly brace and the closing curly brace should be on a new line with no space before it.

For example, the following is good:

class Person {

}

And the following is bad:

class person {}

Constants

Constants should be all upper case. So the following is good:

const FOO = 1;

Dollar Sign

Lots of libraries start their identifier names with the dollar sign. Therefore, to avoid conflict, we should start our identifiers with something else.

Spacing Around Operators

There should be one space between the operand and the operator for binary operators, like + , - , = , * , / and after commas.

For example, the following is good:

let x = y + z;

However, the following is bad:

let x=y+z;

Comma-separated items should have one space after the comma. For example, the following is good:

foo(1, 2, 3);
[1, 2, 3];

But the following code is bad:

foo(1,2,3);
[1,2,3];

Code Indentation

2 spaces for indentation is the accepted convention for indentation:

For example, the following is good:

function foo() {
  let x = 1;
}

But the following is bad:

function foo() {
     let x = 1;
}

It’s better to use spaces instead of tabs since tabs are interpreted differently by different programs and operating systems.

Many text editors can convert tabs to 2 spaces by changing their settings or adding plugins to do it.

Statements

Statements should end with a semicolon at the end.

For example, the following is good:

let x = 1;

But the following is bad:

let x = 1

Omitting semicolon is bad because where the line ends is ambiguous, which is hard to read for developers and the JavaScripr interpreter might not run the code the way you think it does.

For example, if we have:

if (x === 1)
  foo();
  bar();

Then we might think that foo and bar both run when x is 1, but actually, only foo runs since only foo(); is considered to be in the if block.

For complex statements, we should put curly braces around the block and semicolons at the end of each line to make everything clear.

Also, there should be one space before the opening bracket. The closing bracket should be in a new line without any leading spaces. Complex statements shouldn’t end with a semicolon even though it’s allowed.

For instance, we should write functions like:

function foo() {
  let x = 1;
}

Conditional statements should be like:

if (x === 1) {
  y = 1;
} else {
  y = 0;
}

and loops should be like:

for (let i = 1; i <= 10; i++) {
  y = x;
}

Object Literals

Object literals should have space before the opening curly bracket and it should be on the same line as the object name. Properties inside should be left of the colon with no space before it. The value , which is right of the colon, should have one space before it.

The last property shouldn’t have a comma after it.

Quotes should be wrapped around strings only.

The closing bracket should be on a new line with no space before it. Finally, the object literal definition should end with a semicolon.

The following is an example of object definition code with good spacing:

let foo = {
  a: 1,
  b: 2,
  c: 3
}

Shorter objects can also be compressed into one line, with spaces separating the properties as follows:

let foo = { a: 1, b: 2 };

Avoid Long Lines

Lines shorter than 80 characters are preferred for easy reading on smaller screens. We can break long lines into shorters by putting the remainder of the line on the next line.

File Names

Windows filenames aren’t case sensitive. However, most other operating systems have case sensitive file names. Therefore, it’s best to name them all lower case to avoid issues with file name casing.

There’re lots of rules to follow. However, many text editors have text formatting features to clean up the spacing. The other ones can be fixed with a Linter or a program like Prettier to prettify the code.

Categories
JavaScript Design Patterns

Commonly Used Design Patterns in JavaScript

To organize code in a standard way in a program, we have design patterns to enable us to do this.

The book Design Patterns: Elements of Reusable Object-Oriented Software was published in 1994 which came up with 23 design patterns that are used by object-oriented programs.

In this article, we’ll look at some of the more commonly used design patterns in JavaScript programs, including the singleton, iterator and factory patterns.

Singleton

Singleton is a pattern that is common in JavaScript. It’s a class that only creates one instance of an object only.

In JavaScript, we have the object literal to define an object that isn’t an instance of a class. For example, we have:

const obj = {
  foo: 1
}

We also have the class syntax, which does the same thing as constructor functions, where we can define a getInstance method to get an instance of a class.

To make a singleton class, we can write something like the following:

class Foo {
  static getInstance() {
    this.foo = 1;
    this.instance = this;
    return this.instance;
  }
}

const foo1 = Foo.getInstance();
const foo2 = Foo.getInstance();
console.log(foo1 === foo2);

Since we assigned this to this.instance and returns it in getInstance , we should always get the same reference.

We should get that foo1 === foo2 being true since they reference the same instance of the Foo class.

Singleton classes are useful for facade objects to hide the complexities of a program. State objects which are shared by different parts of a program also make singleton classes a good choice.

They also let us share data without creating global variables. Global scope isn’t polluted, so it’s a good choice for sharing data.

Iterator

The iterator pattern is a pattern where we create an iterator to sequentially access data in a container.

We need this pattern to traverse items in collections without exposing the underlying data structure. And we should also be able to traverse objects in an aggregate object without changing its interface.

In JavaScript, we can define iterable objects and generators to do this.

To define an iterable object, we can write:

const iterableObj = {
  *[Symbol.iterator]() {
    let index = 0;
    const arr = [1, 2, 3];
    while (index < arr.length) {
      yield arr[index];
      index++
    }
  }
}

for (const obj of iterableObj) {
  console.log(obj);
}

As we can see iterableObj hides the array that’s inside it from the outside. Also, we can change it to anything else we want and not have to worry about changing the code outside.

[Symbol.iterator] and generator functions have been available since ES6. Ever since then, we can define iterators easily.

We can also define generator functions which return generators. To do this, we can write the following:

const generatorFn = function*() {
  let index = 0;
  const arr = [1, 2, 3];
  while (index < arr.length) {
    yield arr[index];
    index++
  }
}

for (const obj of generatorFn()) {
  console.log(obj);
}

It’s similar to iterableObj since they both use generators. The difference is that generatorFn is a generator function, which returns generators. Generators are what we iterate through.

Factory

The factory pattern centers around the factory function. It’s a function that returns objects without using the new keyword to construct an instance of a class or a constructor function.

We want to use the factory pattern to make code more readable since it lets us create functions that returns new objects from more code.

It also lets us return objects without knowing the code that creates the object. We don’t have to worry about what class is instantiated to create the object or how it’s created otherwise.

In JavaScript, when a function returns an object without the new keyword, then it’s a factory function.

For example, we can create a simple factory function as follows:

const createFoo = () => ({
  foo: 1
});

The createFoo function always returns the { foo: 1 } object when it’s called. It always returns an object without the new keyword, so it’s a factory function and uses the factory pattern.

Factory functions are common in JavaScript. For example, browsers have the document.querySelector() method to get a DOM object given the CSS selector.

There’re similar methods that return objects everywhere in JavaScript.

The singleton pattern creates a single instance of an object. In JavaScript, we can do this with object literals or a getInstance method of a class that always returns the same instance of a class.

It’s useful for sharing data and hiding the complexity of implementation.

The iterator pattern lets us traverse through collections of objects without knowing the implementation of it. Also, it lets us change the underlying data structure and logic without changing the interface.

JavaScript has iterators to do this, in addition to generator functions.

Finally, the factory pattern is common in JavaScript. Anything function that returns a new object without using the new keyword to instantiate it is a factory function.

It’s useful for hiding the complexities of creating objects from other developers. For example, we don’t have to worry about how document.querySelector() gets an element from the DOM. It just returns the first DOM element that matches the selector.

Categories
Quasar

Developing Vue Apps with the Quasar Library — Customize Table Header

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.

Customize Table Header

We can customize the table header by populating the header slot.

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"
            row-key="name"
          >
            <template v-slot:header="props">
              <q-tr :props="props">
                <q-th
                  v-for="col in props.cols"
                  :key="col.name"
                  :props="props"
                  class="text-italic text-purple"
                >
                  {{ col.label }}
                </q-th>
              </q-tr>
            </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
        }
      });
    </script>
  </body>
</html>

We populate the header slot with the q-tr and q-th components to add our own header.

We get the column header data from the prop.cols property and display the label from the col as they are defined in the columns array.

We can also populate the header-cell slot to customize the display of the cells:

<!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"
          >
            <template v-slot:header-cell="props">
              <q-th :props="props">
                <q-icon name="lock_open" size="1.5em"></q-icon>
                {{ props.col.label }}
              </q-th>
            </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
        }
      });
    </script>
  </body>
</html>

Conclusion

We can customize the table’s header by populating the slots provided by the q-table component.

Categories
Quasar

Developing Vue Apps with the Quasar Library — Customize Table Cells

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.

Customize Table Cells

We can customize table cells by populating the body-cell slot:

<!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"
          >
            <template v-slot:body-cell="props">
              <q-td :props="props">
                <q-badge color="blue" :label="props.value"></q-badge>
              </q-td>
            </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
        }
      });
    </script>
  </body>
</html>

We get the table cell’s value with the props.value property from the slot props.

We can customize the cells in one column by populating the body-cell-[name] slot, where [name] is the property name of the column.

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"
            row-key="name"
          >
            <template v-slot:body-cell-name="props">
              <q-td :props="props">
                <q-badge color="blue" :label="props.value"></q-badge>
              </q-td>
            </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
        }
      });
    </script>
  </body>
</html>

Conclusion

We can customize table cells by populating various slots provided by Quasar’s q-table with our own content.

Categories
Quasar

Developing Vue Apps with the Quasar Library — Custom Table Content

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.

Custom Table Top

We can change the content of the top of the table by populating the top slot.

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" row-key="id">
            <template v-slot:top>
              <q-btn color="primary" label="Add row" @click="addRow"></q-btn>
              <q-btn
                class="q-ml-sm"
                color="primary"
                label="Remove row"
                @click="removeRow"
              >
              </q-btn>
            </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
        },
        methods: {
          addRow() {
            this.data.push(
              this.data[Math.floor(Math.random() * this.data.length)]
            );
          },
          removeRow() {
            this.data.splice(Math.floor(Math.random() * this.data.length), 1);
          }
        }
      });
    </script>
  </body>
</html>

We add 2 buttons into the top slot to add and remove rows from the table respectively.

Custom Table Body Content

We can customize the table body content by populating the body slot:

<!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"
          >
            <template v-slot:body="props">
              <q-tr :props="props">
                <q-td key="name" :props="props">
                  {{ props.row.name }}
                </q-td>
                <q-td key="calories" :props="props">
                  <q-badge color="green">
                    {{ props.row.calories }}
                  </q-badge>
                </q-td>
                <q-td key="fat" :props="props">
                  <q-badge color="purple">
                    {{ props.row.fat }}
                  </q-badge>
                </q-td>
                <q-td key="calcium" :props="props">
                  <q-badge color="accent">
                    {{ props.row.calcium }}
                  </q-badge>
                </q-td>

                </q-td>
              </q-tr>
            </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
        },
      });
    </script>
  </body>
</html>

We get the table cell data from the slot props.

And we render the items inside the q-td component however we like.

Conclusion

We can customize the table’s top and body content with the slots provided by Quasar’s q-table component.