Categories
JavaScript Vue

Render Elements Conditionally with Vue.js with v-if

Vue.js is an easy to use web app framework that we can use to develop interactive front end apps.

In this article, we’ll look at various ways to render items conditionally on the screen with Vue.js by using the v-if , v-else-if and v-else directives.

v-if

The v-if directive is used to conditionally render a block. The block with the v-if attribute will be rendered only if the directive’s expression returns a truthy value.

For example, in src/index.js we put:

new Vue({  
  el: "#app",  
  data: {  
    show: true  
  }  
});

Then in index.html , we put:

<!DOCTYPE html>  
<html>  
  <head>  
    <title>App</title>  
    <meta charset="UTF-8" />  
    <script src="https://cdn.jsdelivr.net/npm/vue/dist/vue.js"></script>  
  </head> <body>  
    <div id="app">  
      <div v-if="show">  
        Hi  
      </div>  
    </div>  
    <script src="src/index.js"></script>  
  </body>  
</html>

Then Hi will be shown since show is set to true .

We can also use v-else in addition to v-if if we want to show something if an expression returns false .

For example, if we change true to false in src/index.js :

new Vue({  
  el: "#app",  
  data: {  
    show: false  
  }  
});

Then in index.html , if we have:

<!DOCTYPE html>  
<html>  
  <head>  
    <title>App</title>  
    <meta charset="UTF-8" />  
    <script src="https://cdn.jsdelivr.net/npm/vue/dist/vue.js"></script>  
  </head> <body>  
    <div id="app">  
      <div v-if="show">Hi</div>  
      <div v-else>Bye</div>  
    </div>  
    <script src="src/index.js"></script>  
  </body>  
</html>

Then we see Bye because show is set to false and we have v-else directive added to an element that is the sibling of the element that immediately follows the element with thev-if directive.

v-if on template Elements to Toggle Groups of Elements

We can add v-if to a group of elements by wrapping them around a template element.

For example, we can write:

<template v-if="show">  
  <p>foo</p>  
  <p>bar</p>  
</template>

Then foo and bar will be shown if show is set to true .

v-else

We can use the v-else directive to display something when the expression in the v-if directive in a sibling element that immediately follows the element with v-if returns false .

For example, we can display messages randomly as follows. In index.html , we put:

<!DOCTYPE html>  
<html>  
  <head>  
    <title>App</title>  
    <meta charset="UTF-8" />  
    <script src="https://cdn.jsdelivr.net/npm/vue/dist/vue.js"></script>  
  </head> <body>  
    <div id="app">  
      <div v-if="Math.random() > 0.5">  
        Hi  
      </div>  
      <div v-else>  
        Bye  
      </div>  
    </div>  
    <script src="src/index.js"></script>  
  </body>  
</html>

And in src/index.js , we put:

new Vue({  
  el: "#app",  
  data: {}  
});

v-else-if

v-if can also be followed with an element with the v-else-if directive, so that we can have multiple elements conditionally displayed.

For example, we can write index.html as follows:

<!DOCTYPE html>  
<html>  
  <head>  
    <title>App</title>  
    <meta charset="UTF-8" />  
    <script src="https://cdn.jsdelivr.net/npm/vue/dist/vue.js"></script>  
  </head> <body>  
    <div id="app">  
      <div v-if="Math.random() > 0.8">  
        A  
      </div>  
      <div v-else-if="Math.random() > 0.5 && Math.random() <= 0.8">  
        B  
      </div>  
      <div v-else>  
        C  
      </div>  
    </div>  
    <script src="src/index.js"></script>  
  </body>  
</html>

Then we’ll have A, B and C displayed according to what’s returned from Math.random() .

This is available since Vue 2.1.0.

Controlling Reusable Elements with key

Vue tries to reuse existing elements as much as possible when conditionally rendering items.

This means sometimes we get things that we don’t expect.

For example, if we have the following in src/index.js :

new Vue({  
  el: "#app",  
  data: {  
    loginType: "username"  
  },  
  methods: {  
    toggleType() {  
      this.loginType = this.loginType === "username" ? "email" : "username";  
    }  
  }  
});

And the following in index.html :

<!DOCTYPE html>  
<html>  
  <head>  
    <title>App</title>  
    <meta charset="UTF-8" />  
    <script src="https://cdn.jsdelivr.net/npm/vue/dist/vue.js"></script>  
  </head> <body>  
    <div id="app">  
      <button @click="toggleType">Change Login Type</button>  
      <template v-if="loginType === 'username'">  
        <label>Username</label>  
        <input placeholder="Enter your username" />  
      </template>  
      <template v-else>  
        <label>Email</label>  
        <input placeholder="Enter your email address" />  
      </template>  
    </div>  
    <script src="src/index.js"></script>  
  </body>  
</html>

Then when we click the Change Login Type button after entering something to the input, we get the same input value displayed after changing the template.

To make the input render from scratch, we can add a key attribute to the the key attribute with different values for each input.

So instead of what we have above for index.html, we can write:

<!DOCTYPE html>  
<html>  
  <head>  
    <title>App</title>  
    <meta charset="UTF-8" />  
    <script src="https://cdn.jsdelivr.net/npm/vue/dist/vue.js"></script>  
  </head> <body>  
    <div id="app">  
      <button @click="toggleType">Change Login Type</button>  
      <template v-if="loginType === 'username'">  
        <label>Username</label>  
        <input placeholder="Enter your username" key="username" />  
      </template>  
      <template v-else>  
        <label>Email</label>  
        <input placeholder="Enter your email address" key="email" />  
      </template>  
    </div>  
    <script src="src/index.js"></script>  
  </body>  
</html>

Then the inputs will be cleared.

Everything else is still reused efficiently since we didn’t add the key attribute.

Conclusion

We can render things conditionally with v-if . The element with v-if added will be displayed when the expression that we set as the value returns true .

We can use it in conjunction with v-else-if and v-else , where we can provide elements that are displayed when the condition in v-if returns false .

Elements with v-else-if are displayed when the condition returns a truthy value and the one in v-if returns a falsy value. It must be added immediately below an element with v-if .

An element with v-else can be added below an element with v-if if there’s no element with v-else-if . If there’s one or more elements with v-else-if , then the v-else element has to be added below it.

v-else can be used to display something if all other conditions are falsy.

Categories
JavaScript Vue

Create a Vue.js Stopwatch

We can create a stopwatch using Vue.js by using built in functions. In this article, we’ll find out how to make a simple stopwatch.

To start, we create new project with the Vue CLI by running npx @vue/cli.

We then select the default options to create a new Vue project.

Next, we can write the following code:

<template>
  <div id="app">
    <button @click="start">Start</button>
    <button @click="stop">Stop</button>
    <button @click="reset">Reset</button>
    <p>{{formattedElapsedTime}}</p>
  </div>
</template>

<script>
export default {
  name: "App",
  data() {
    return {
      elapsedTime: 0,
      timer: undefined
    };
  },
  computed: {
    formattedElapsedTime() {
      const date = new Date(null);
      date.setSeconds(this.elapsedTime / 1000);
      const utc = date.toUTCString();
      return utc.substr(utc.indexOf(":") - 2, 8);
    }
  },
  methods: {
    start() {
      this.timer = setInterval(() => {
        this.elapsedTime += 1000;
      }, 1000);
    },
    stop() {
      clearInterval(this.timer);
    },
    reset() {
      this.elapsedTime = 0;
    }
  }
};
</script>

In the code above, we have the Start, Stop, and Reset buttons. Then we click thev Start, the start method is run, which creates the timer with setInterval and the this.elapsedTime state is updated.

The elapsedTime is converted to a formatted time string with minutes and seconds with the formattedElapsedTime computed property,

The Stop button runs the stop method when it’s clicked, which calls clearInterval to clear the timer.

The reset method is called by the Reset button and resets this.elapsedTime to 0.

Then we’ll see the stopwatch run when we click Start and the timer stops when we click Stop.

The stopwatch goes back to 0 after we click Reset.

Conclusion

We can create a Vue.js stopwatch without adding extra libraries. We just have to use setInterval and clearInterval to start and stop the stopwatch respectively.

Categories
JavaScript Vue

Getting Started with Vue.js

Vue.js is an easy to use web app framework that we can use to develop interactive front end apps.

In this article, we’ll look at how to add the Vue.js framework to our app and build our first app.

Script Tag

We can include the Vue.js framework with a script tag.

To do this we can write:

<script src='https://vuejs.org/js/vue.js'></script>

before our app code loads. The URL above has the development version, which has all the warnings but it’s not minified.

To include the production version, we can write:

<script src='https://vuejs.org/js/vue.min.js'></script>

To fix the version to 2.6.11, we can write:

<script src="https://cdn.jsdelivr.net/npm/vue@2.6.11"></script>

We can also import the module in our browser if we don’t need to support Internet Explorer as follows:

<script type="module">     
  import Vue from 'https://cdn.jsdelivr.net/npm/vue@2.6.11/dist/vue.esm.browser.js' 
</script>

The vue.esm.browser.js file is already optimized for browsers so it can be used without creating too many requests.

Example

To create our first app, we can create the index.html file as follows:

<!DOCTYPE html>  
<html>  
  <head>  
    <title>Parcel Sandbox</title>  
    <meta charset="UTF-8" />  
    <script src="https://vuejs.org/js/vue.js"></script>  
  </head> <body>  
    <div id="app"></div>  
    <script src="./src/index.js"></script>  
  </body>  
</html>

Then in src/index.js , we can add:

new Vue({  
  template: "<div>{{ 'hello' }}</div>",  
  el: "#app"  
});

Then we should see hello on the screen, since we have a div with the ID app , which is used by Vue.js to render our Vue instance.

The Vue.js compiler is responsible for converting the template into HTML.

In the template above, 'hello' is a JavaScript string, which was converted to HTML text when the Vue compiler runs.

We specified that the template has a div with the text 'hello' in it.

Different Builds of the Vue.js Framework

There are several different builds of the Vue.js framework. They’re:

  • Full — Builds that have the compiler and the runtime. That’s the one we used in the example above.
  • Compiler — Code that’s responsible for compiling template strings into JavaScript render functions
  • Runtime — Code that’s responsible for creating Vue instances, rendering and updating virtual DOM, etc.
  • UMD — A module that can be directly included with a script tag. It includes the runtime and the compiler
  • CommonJS — A module that can be used with older bundlers like Browserify or Webpack 1.
  • ES Module — New to version 2.6. It can be used directly by browsers via <script type='module'> or be used with bundlers like Webpack 2 or Rollup.

Runtime and Compiler

The runtime is used for creating the Vue instance via new Vue .

The compiler is for compiling templates specified by the template option.

This means that:

new Vue({  
  template: "<div>{{ 'hello' }}</div>",  
  el: "#app"  
});

needs the compiler and:

new Vue({  
  el: "#app",  
  render(h) {  
    return h("div", "hello");  
  }  
});

doesn’t.

Template syntax will be much more convenient when our apps get more complex.

When we’re using vue-loader or vueify , templates inside .vue files are precompiled into JavaScript, so we don’t need the compiler in the final bundle.

When we don’t need to use the compiler, then we should use the runtime only build since it’s 30% smaller.

We can include different builds depending on the bundler that we’re using. For example, in Parcel, we can write:

"alias": {       
  "vue" : "./node_modules/vue/dist/vue.common.js"     
}

in package.json .

Vue CLI

We can Vue-CLI automatically create our app and build it so we don’t have to worry about which bundles to choose.

To install it, we can run:

npm install -g @vue/cli

or:

yarn global add @vue/cli

We can then create a project with it by running:

vue create project

or run:

vue ui

to show the GUI to let us create a Vue project in our browser.

Also, we can run the Vue CLI directly with npx by running:

npx vue create project

Running vue create will present us with a wizard with various options like:

Vue CLI v3.11.0  
┌───────────────────────────┐  
│  Update available: 4.1.2  │  
└───────────────────────────┘  
? Please pick a preset: Manually select features  
? Check the features needed for your project: (Press <space> to select, <a> to toggle all, <i> to invert selection)  
>(*) Babel  
 ( ) TypeScript  
 ( ) Progressive Web App (PWA) Support  
 ( ) Router  
 ( ) Vuex  
 ( ) CSS Pre-processors  
 (*) Linter / Formatter  
 ( ) Unit Testing  
 ( ) E2E Testing

This screen is presented when we choose Manually Select Features . We can choose Default if we don’t want to choose anything from this screen.

To run the Vue UI, we can run:

npx vue ui

Then our browser will automatically go to http://localhost:8000/project/select, where we see a Create link to create a project.

We can then create a project by clicking Create a new project here once we clicked on the Create tab.

Conclusion

We can create a new Vue.js app by including it via a script tag or using the Vue CLI or the Vue UI web app.

To get started, we added Vue.js with a script tag and then create a new Vue instance to create an app.

There are various builds of the Vue.js framework. If we need templates, we need the full build unless it’s prebuilt with vue-loader or vueify .

Otherwise, we can use the runtime-only build to reduce the size of it.

Categories
JavaScript Vue

Useful Vue Notification Components That’ll Save You Time

Vue.js is an easy to use web app framework that we can use to develop interactive front end apps.

In this article, we’ll look at some Vue notification libraries that’ll save you time. They’re used for display popup notifications your way.

vue-notifications

vue-notifications is a library to let us display pop-up notifications without creating them ourselves.

To install it, we run:

npm i vue-notifications mini-toastr --save

Then we write the following code to import the library and use it:

main.js:

import Vue from "vue";
import App from "./App.vue";
import VueNotifications from "vue-notifications";
import miniToastr from "mini-toastr";
const toastTypes = {
  success: "success",
  error: "error",
  info: "info",
  warn: "warn"
};
miniToastr.init({ types: toastTypes });
const toast = ({ title, message, type, timeout, cb }) => {
  return miniToastr[type](message, title, timeout, cb);
};
const options = {
  success: toast,
  error: toast,
  info: toast,
  warn: toast
};
Vue.use(VueNotifications, options);
Vue.config.productionTip = false;
new Vue({
  render: h => h(App)
}).$mount("#app");

In the code above, we add the mini-toastr to configure and show toast popups. We added various types of toasts and then imported the VueNotifications dependency on the options as the type. The toast function calls miuniToastr to create the popup according to the types given.

The parameters in the toast callback has the following meanings:

  • title - string for the notification title
  • message - string for the message
  • timeout - number of milliseconds before the notification is gone
  • cb - callback function

App.vue :

<template>
  <div id="app">
    <button @click="show">Show Greeting</button>
  </div>
</template>
<script>
export default {
  name: "App",
  notifications: {
    showGreeting: {
      title: "Hello",
      message: "Hello world",
      type: "info"
    }
  },
  methods: {
    show() {
      this.showGreeting();
    }
  }
};
</script>

In the App component, we just add the notifications property with a property, which is the name of the function to display the message. Then inside, we set the title, message, and type according to the ones listed in main.js .

Then when we click the button, we see a toast shown with Hello as the title and Hello world as the message in blue background.

vue-easy-toast

vue-easy-toast is very easy to use as its name suggests. To install it, we run:

npm install vue-easy-toast --save

Then to use it, we write the following code:

main.js :

import Vue from "vue";
import App from "./App.vue";
import Toast from "vue-easy-toast";
Vue.use(Toast);
Vue.config.productionTip = false;
new Vue({
  render: h => h(App)
}).$mount("#app");

App.vue :

<template>
  <div id="app">
    <button @click="showToast">Show Toast</button>
  </div>
</template>
<script>
export default {
  name: "App",
  methods: {
    showToast() {
      this.$toast("Toast.");
    }
  }
};
</script>

All we did was import the package with Vue.use and then call the $toast method added by vue-easy-toast to display a toast.

Then when we click the Show Toast button, we see the Toast. message displayed. We can also have HTML in our message string. Other options include:

  • id - string for a unique identifier
  • parent - string for the container to display the toast in
  • className - class name for the toast, can be a string or an array of strings
  • horizontalPosition - the horizontal position of the toast as a string
  • verticalPosition - vertical position of the toast as a string
  • duration - number of ms to display the toast
  • mode - a string that can take the value override or queue . If override , the last toast will forcibly flush previous.
  • closesable - boolean value for enabling closing toast manually
  • transition - string for built-in transformation name, which can be fade or slide-[up/down/left/right]

vue-notification

vue-notification is another easy to use notification library for showing notifications. To install it, we run:

npm install --save vue-notification

Then we can use it as follows:

main.js :

import Vue from "vue";
import App from "./App.vue";
import Notifications from "vue-notification";
Vue.use(Notifications);
Vue.config.productionTip = false;
new Vue({
  render: h => h(App)
}).$mount("#app");

App.vue :

<template>
  <div id="app">
    <notifications group="foo"/>
    <button @click="showToast">Show Toast</button>
  </div>
</template>
<script>
export default {
  name: "App",
  methods: {
    showToast() {
      this.$notify({
        group: "foo",
        title: "Important message",
        text: "Hello user!"
      });
    }
  }
};
</script>

We just have to import the library with Vue.use, and then we can call the $notify method that comes with vue-notification to display a message once we added the notification component to our template with the given group.

Then when we click the Show Toast button, we’ll see a blue popup with our message.

Conclusion

These libraries are all very useful for display notifications. Some libraries, like vue-easy-notification and vue-notification are easier than the other ones.

Categories
JavaScript Vue

Useful Vue Data Grid Components

Vue.js is an easy to use web app framework that we can use to develop interactive front end apps.

In this article, we’ll look at some data grid components that we can use to build data grids.

vue-handsontable-official

This is a Vue data grid that looks and feels like a spreadsheet. It’s the official Vue wrapper for Handsontable.

We can run:

npm install handsontable @handsontable/vue

to install it. Then we can use it as follows:

<template>
  <div id="app">
    <hot-table
      licenseKey="non-commercial-and-evaluation"
      :data="data"
      :colHeaders="true"
      :rowHeaders="true"
      width="600"
      height="300"
    ></hot-table>
  </div>
</template>
<script>
import { HotTable } from "@handsontable/vue";
export default {
  data() {
    return {
      data: [
        ["", "Mazda", "Honda", "Toyota", "Volvo"],
        ["2019", 10, 11, 12, 13],
        ["2020", 20, 11, 14, 13],
        ["2021", 30, 15, 12, 13]
      ]
    };
  },
  components: {
    HotTable
  }
};
</script>
<style lang="scss">
@import "~handsontable/dist/handsontable.full.css";
</style>

In the code above, we registered the HotTable component in our component. Then we have the data model, which we pass int the data prop of the hot-table component.

Also, we set colHeaders and rowHeaders to true so that we see the column and row headings. This should result in a data grid that looks like a spreadsheet, with letters as column headers and numbers as row headers.

Like a spreadsheet, we can also add context menus for the cells by adding the contextMenu object as follows:

<template>
  <div id="app">
    <hot-table
      licenseKey="non-commercial-and-evaluation"
      :data="data"
      :colHeaders="true"
      :rowHeaders="true"
      width="600"
      height="300"
      :contextMenu="contextMenu"
    ></hot-table>
  </div>
</template>
<script>
import { HotTable } from "@handsontable/vue";
import Handsontable from "handsontable";
export default {
  data() {
    return {
      data: [
        ["", "Tesla", "Mercedes", "Toyota", "Volvo"],
        ["2019", 10, 11, 12, 13],
        ["2020", 20, 11, 14, 13],
        ["2021", 30, 15, 12, 13]
      ],
      contextMenu: {
        items: {
          row_above: {
            name: "Insert row above this one"
          },
          row_below: {},
          separator: Handsontable.plugins.ContextMenu.SEPARATOR,
          clear_custom: {
            name: "Clear all cells",
            callback() {
              this.clear();
            }
          }
        }
      }
    };
  },
  components: {
    HotTable
  }
};
</script>
<style lang="scss">
@import "~handsontable/dist/handsontable.full.css";
</style>

We added the contextMenu object, which has the row_above property for adding a context menu entry for inserting a new row above the current one. Then we added the row_below property to add an Insert row below menu item, but set the value to an empty object so that we keep the default settings.

Then we added a clear_custom property to add an entry to clear all cells.

There’re many more options, including customizing the editor, changing how cells are rendered, integration with Vuex and more.

The full list of options are at https://handsontable.com/docs/7.4.0/tutorial-introduction.html.

It’s free for non-commercial and evaluation purpose, but it’s a paid library for commercial purposes.

vue-sorted-table

vue-sorted-table is another table component that automatically generates a table from data. It makes adding the column sorting feature easy. To install it, we run:

npm install --save vue-sorted-table

Then to use it, we write the following code:

main.js :

import Vue from "vue";
import App from "./App.vue";
import SortedTablePlugin from "vue-sorted-table";
Vue.use(SortedTablePlugin);
Vue.config.productionTip = false;
new Vue({
  render: h => h(App)
}).$mount("#app");

App.vue :

<template>
  <div id="app">
    <sorted-table :values="values">
      <thead>
        <tr>
          <th scope="col" style="text-align: left; width: 10rem;">
            <sort-link name="id">ID</sort-link>
          </th>
          <th scope="col" style="text-align: left; width: 10rem;">
            <sort-link name="name">Name</sort-link>
          </th>
          <th scope="col" style="text-align: left; width: 10rem;">
            <sort-link name="hits">Age</sort-link>
          </th>
        </tr>
      </thead>
      <tbody slot="body" slot-scope="sort">
        <tr v-for="value in sort.values" :key="value.id">
          <td>{{ value.id }}</td>
          <td>{{ value.name }}</td>
          <td>{{ value.age }}</td>
        </tr>
      </tbody>
    </sorted-table>
  </div>
</template>
<script>
export default {
  name: "App",
  data: function() {
    return {
      values: [
        { name: "James", id: 2, age: 33 },
        { name: "Mary", id: 1, age: 42 },
        { name: "Alex", id: 3, age: 79 }
      ]
    };
  }
};
</script>

In the code above, we have the values array, which is used as the data for our sorted-table component. Then we add the table rows by using the regular HTML tr element.

In the table header, we add the sort-link component to each th element to let us sort each column individually.

We can also add icons for the up and down arrows used for the sort-link by passing in a second argument info Vue.use as follows:

Vue.use(SortedTablePlugin, {
  ascIcon: '<i class="material-icons">arrow_drop_up</i>',
  descIcon: '<i class="material-icons">arrow_drop_down</i>'
});

Also, the objects containing the values have to be a flat object. Other optional available include values , dir , sort , ascIcon , descIcon ,onSort . values is an array of objects containing the table values. dir is the sort direction, sort is the default sorting column, ascIcon and descIcon are the icons for the sort arrows, and onSort is a callback for custom sorting.

Conclusion

We can add tables easily with Vue Handsontable and vue-sorted-table . Vue Handsontable is more full-featured and works like a spreadsheet with its ability to edit cells and add/remove columns. vue-sorted-table is simpler. Its only purpose is to provide sorting on table columns.