Categories
JavaScript Vue

Introduction to Vue.js Watchers

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 define and use Vue.js watchers.

When Should We Use Watchers?

We can use watchers when we want to watch for data changes in reactive properties and do some asynchronous or expensive options as the value changes.

For example, we can use it to watch for changes for an input and then get a joke from the Chuck Norris API when we type in something.

First, we put the following in src/index.js :

new Vue({  
  el: "#app",  
  data: {  
    message: "",  
    joke: ""  
  },  
  created() {  
    this.debounceGetAllCapsMessage = _.debounce(this.getAllCapsMessage, 500);  
  },  
  methods: {  
    async getAllCapsMessage() {  
      const res = await fetch("https://api.icndb.com/jokes/random");  
      const result = await res.json();  
      this.joke = result.value.joke;  
    }  
  },  
  watch: {  
    message(newMessage, oldMessage) {  
      this.debounceGetAllCapsMessage();  
    }  
  }  
});

The code above watches for the change in the message property and then call the debounceGetAllCapsMessage method, which gets a jokes after a half a second delay.

The watch method both takes the new value as the first parameter and the old value as the second parameter.

Then we put the following in index.html :

<!DOCTYPE html>  
<html>  
  <head>  
    <title>Hello</title>  
    <meta charset="UTF-8" />  
    <script src="https://cdn.jsdelivr.net/npm/vue/dist/vue.js"></script>  
    <script src="https://cdn.jsdelivr.net/npm/lodash@4.13.1/lodash.min.js"></script>  
  </head> <body>  
    <div id="app">  
      <input type="text" v-model="message" />  
      <p>{{joke}}</p>  
    </div>  
    <script src="./src/index.js"></script>  
  </body>  
</html>

As we can see, we can run an asynchronous operation, add a delay before we perform the operation, and then get the final result.

We can also use vm.$watch to watch for a value. It takes up to 3 arguments.

The first is a path to a property, which is a string. It can also be a function with one or multiple things combined to watch.

The second argument is a function that runs when the value changes.

The third argument for vm.$watch is an object with some properties. They include:

  • immediate — watches for the setting of the initial value

The method returns a function to stop watching for values. This is an optional argument.

We can use it as follows. In src/index.js , we have:

const vm = new Vue({  
  el: "#app",  
  data: {  
    message: "",  
    joke: ""  
  }  
});

vm.$watch(  
  "message",  
  _.debounce(async function() {  
    const res = await fetch("https://api.icndb.com/jokes/random");  
    const result = await res.json();  
    this.joke = result.value.joke;  
  }, 500)  
);

Then index.html , we have:

<!DOCTYPE html>  
<html>  
  <head>  
    <title>Hello</title>  
    <meta charset="UTF-8" />  
    <script src="https://cdn.jsdelivr.net/npm/vue/dist/vue.js"></script>  
    <script src="https://cdn.jsdelivr.net/npm/lodash@4.13.1/lodash.min.js"></script>  
  </head> <body>  
    <div id="app">  
      <input type="text" v-model="message" />  
      <p>{{joke}}</p>  
    </div>  
    <script src="./src/index.js"></script>  
  </body>  
</html>

which is the same as what we had before.

In both examples, we should get a new joke after half a second delay displayed.

Conclusion

We can use the watch method in the options and object and vm.$watch to watch for value changes.

The vm.$watch method watches a property given the path to it or a function that returns it or a combination of multiple properties.

vm.$watch takes a value changes handler and we can run code in it to handle when the value of a reactive property change.

The watch method runs code as the value changes.

Also, the watch method both takes the new value as the first parameter and the old value as the second parameter.

Categories
JavaScript Vue

Introduction to Vue.js Computed Properties and Watchers

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 Vue.js computed properties and watchers.

Computed Properties

To make more template expressions more concise and reusable, we can create computed properties to compute results from existing properties as their value changes.

We can define computed properties in a Vue instance by putting them in the computed property of the options object that we pass into the Vue constructor.

For example, we can write the following in src/index.js:

new Vue({  
  el: "#app",  
  data: {  
    message: "foo"  
  },  
  computed: {  
    spelledMessage() {  
      return this.message.split("").join("-");  
    }  
  }  
});

Then we can use it like any other field in our HTML template. So in index.html, we can write:

<!DOCTYPE html>  
<html>  
  <head>  
    <title>Hello</title>  
    <meta charset="UTF-8" />  
    <script src="https://cdn.jsdelivr.net/npm/vue/dist/vue.js"></script>  
  </head> <body>  
    <div id="app">  
      <p>{{message}}</p>  
      <p>{{spelledMessage}}</p>  
    </div>  
    <script src="./src/index.js"></script>  
  </body>  
</html>

We should then get:

foof-o-o

on our screen.

The spelledMessage method is a getter that’s used by Vue.js. It takes the returned value of it and then put it in place of {{spelledMessage}} .

Therefore, the name of the placeholder in the template must be the same as the name of the method that returns the value that we want in the computed object.

We can also get the value from the returned Vue instance as follows:

const vm = new Vue({  
  el: "#app",  
  data: {  
    message: "foo"  
  },  
  computed: {  
    spelledMessage() {  
      return this.message.split("").join("-");  
    }  
  }  
});

console.log(vm.spelledMessage);

We should see f-o-o logged from the console.log.

We can bind to computed properties in templates like any other property. Vue knows that vm.spelledMessage depends on vm.message, so the bindings will be updated when vm.message is updated.

The computed getter method doesn’t commit side effects, which makes it easy to test and understand.

Computed Caching vs Methods

One good feature of computed properties is that the result of it is cached.

There’s no caching for results returned from methods.

So instead of using methods, we should use computed properties for cases where we’re computing something from existing properties.

A computed property is only re-evaluated once a reactive property is updated.

For example, if we have:

const vm = new Vue({  
  el: "#app",  
  data: {  
    message: "foo"  
  },  
  computed: {  
    now() {  
      return Date.now();  
    }  
  }  
});

It’ll never update after its first computed since it doesn’t depend on any reactive property from the data property.

Without caching computed properties keep getting computed as reactive properties that they depend on change, which means the app gets slow as reactive properties that the computed property depends on are changing.

Computed vs Watched Property

Watch properties are useful for watching for changes in a property as the name suggests.

However, because of the caching feature of computed properties, we should use them as much as we can.

For instance, we can simplify the following:

new Vue({  
  el: "#app",  
  data: {  
    name: "Joe",  
    age: 1,  
    person: undefined  
  },  
  watch: {  
    name: {  
      immediate: true,  
      handler(newVal) {  
        this.person = `${newVal} - ${this.age}`;  
      }  
    },  
    age: {  
      immediate: true,  
      handler(newVal) {  
        this.person = `${this.name} - ${newVal}`;  
      }  
    }  
  }  
});

to:

new Vue({  
  el: "#app",  
  data: {  
    name: "Joe",  
    age: 1  
  },  
  computed: {  
    person() {  
      return `${this.name} - ${this.age}`;  
    }  
  }  
});

As we can see, the first example was much more complex. We have to set immediate to true in each property so that it’ll watch the initial value change. Then we have to define the value change handler for each reactive property.

Then in each handler, we have to set the person property so that we can combine name and age.

On the other hand, with computed properties, we only have one method which returns the fields combined in the way we want.

It’s much more convenient for us and the app that we create is also faster because of caching.

Computed Setter

We can also create a setter function for computed properties.

For example, we can write:

new Vue({  
  el: "#app",  
  data: {  
    name: "Joe",  
    age: 1  
  },  
  computed: {  
    person: {  
      get() {  
        return `${this.name} - ${this.age}`;  
      },  
      set(newValue) {  
        const [name, age] = newValue.split("-");  
        this.name = name.trim();  
        this.age = age.trim();  
      }  
    }  
  }  
});

The getter function returns the same thing as before, but now we also have a setter function.

The setter function splits the newValue, which has the computed value from the getter function, we split the result and set the result back to the corresponding reactive properties.

We can use a setter as follows. We can put the following in src/index.js:

new Vue({  
  el: "#app",  
  data: {  
    firstName: "Joe",  
    lastName: "Smith"  
  },  
  computed: {  
    name: {  
      get() {  
        return `${this.firstName} ${this.lastName}`;  
      },  
      set(newValue) {  
        const [firstName, lastName] = newValue.split(" ");  
        this.firstName = (firstName || "").trim();  
        this.lastName = (lastName || "").trim();  
      }  
    }  
  }  
});

And in index.html, we put:

<!DOCTYPE html>  
<html>  
  <head>  
    <title>Hello</title>  
    <meta charset="UTF-8" />  
    <script src="[https://cdn.jsdelivr.net/npm/vue/dist/vue.js](https://cdn.jsdelivr.net/npm/vue/dist/vue.js)"></script>  
  </head> <body>  
    <div id="app">  
      <p>{{name}}</p>  
      <input type="text" v-model="name" />  
    </div>  
    <script src="./src/index.js"></script>  
  </body>  
</html>

Then when we change the value in the input, we get the new values assigned back to the firstName and lastName fields with the setter.

Conclusion

We can use computed properties to compute values from existing properties.

Returned values from computed properties are cached to reduce the amount of computation required.

Computed properties can also have setters, where we can do things with the new values returned from the computed property getter.

Categories
Express JavaScript Vue

Guide to the Express Request Object — Queries and Cookies

The request object lets us get the information about requests made from the client in middlewares and route handlers.

In this article, we’ll look at the properties of Express’s request object in detail, including query strings, URL parameters, and signed cookies.

Request Object

The req parameter we have in the route handlers above is the req object.

It has some properties that we can use to get data about the request that’s made from the client-side. The more important ones are listed below.

req.originalUrl

The originalUrl property has the original request URL.

For example, we can use it as follows:

const express = require('express');  
const bodyParser = require('body-parser');  
const app = express();
app.get('/', (req, res) => {  
  res.send(req.originalUrl);  
})
app.listen(3000);

Then when we have the request with query string /?foo=bar , we get back /?foo=bar .

req.params

params property has the request parameters from the URL.

For example, if we have:

const express = require('express')  
const app = express()
app.use(express.json())  
app.use(express.urlencoded({ extended: true }))

app.get('/:name/:age', (req, res) => {  
  res.json(req.params)  
})

app.listen(3000, () => console.log('server started'));

Then when we pass in /john/1 as the parameter part of the URL, then we get:

{  
    "name": "john",  
    "age": "1"  
}

as the response from the route above.

req.path

The path property has the path part of the request URL.

For instance, if we have:

const express = require('express');  
const bodyParser = require('body-parser');  
const app = express();

app.get('/:name/:age', (req, res) => {  
  res.send(req.path);  
})

app.listen(3000);

and make a request to /foo/1 , then we get back the same thing in the response.

req.protocol

We can get the protocol string with the protocol property.

For example, if we have:

const express = require('express');  
const bodyParser = require('body-parser');  
const app = express();
app.get('/', (req, res) => {  
  res.send(req.protocol);  
})

app.listen(3000);

Then when we make a request through HTTP we get backhttp .

req.query

The query property gets us the query string from the request URL parsed into an object.

For example, if we have:

const express = require('express')  
const app = express()
app.use(express.json())  
app.use(express.urlencoded({ extended: true }))
app.get('/', (req, res) => {  
  res.json(req.query)  
})

app.listen(3000, () => console.log('server started'));

Then when we append ?name=john&age=1 to the end of the hostname, then we get back:

{  
    "name": "john",  
    "age": "1"  
}

from the response.

req.route

We get the current matched route with the route property.

For example, we can use it as follows:

const express = require('express');  
const bodyParser = require('body-parser');  
const app = express();

app.get('/', (req, res) => {  
  console.log(req.route);  
  res.json(req.route);  
})

app.listen(3000);

Then we get something like the following from the console.log :

Route {  
  path: '/',  
  stack:  
   [ Layer {  
       handle: [Function],  
       name: '<anonymous>',  
       params: undefined,  
       path: undefined,  
       keys: [],  
       regexp: /^\/?$/i,  
       method: 'get' } ],  
  methods: { get: true } }

req.secure

A boolean property that indicates if the request is made with via HTTPS.

For example, given that we have:

const express = require('express');  
const bodyParser = require('body-parser');  
const app = express();
app.get('/', (req, res) => {    
  res.json(req.secure);  
})

app.listen(3000);

Then we get false if the request is made via HTTP.

req.signedCookies

The signedCookies object has the cookie with the value deciphers from the hashed value.

For example, we can use it as follows:

const express = require('express');  
const bodyParser = require('body-parser');  
const cookieParser = require('cookie-parser');  
const app = express();  
app.use(cookieParser('secret'));
app.get('/cookie', (req, res, next) => {  
  res.cookie('name', 'foo', { signed: true })  
  res.send();  
})

app.get('/', (req, res) => {  
  res.send(req.signedCookies.name);  
})

app.listen(3000);

In the code above, we have the /cookie route to send the cookie from our app to the client. Then we can get the value from the client and then make a request to the / route with the Cookie header with name as the key and the signed value from the /cookie route as the value.

For example, it would look something like:

name=s%3Afoo.dzukRpPHVT1u4g9h6l0nV6mk9KRNKEGuTpW1LkzWLbQ

Then we get back foo from the / route after the signed cookie is decoded.

req.stale

stale is the opposite of fresh . See [req.fresh](https://expressjs.com/en/4x/api.html#req.fresh) for more details.

req.subdomains

We can get an array of subdomains in the domain name of the request with the subdomains property.

For example, we can use it as follows:

const express = require('express');  
const bodyParser = require('body-parser');  
const app = express();

app.get('/', (req, res) => {  
  res.send(req.subdomains);  
})

app.listen(3000);

Then when we make a request to the / route, we get something like:

["beautifulanxiousflatassembler--five-nine"]

req.xhr

A boolean property that’s true is X-Requested-With request header field is XMLHttpRequest .

For example, we can use it as follows:

const express = require('express');  
const bodyParser = require('body-parser');  
const app = express();

app.get('/', (req, res) => {  
  res.send(req.xhr);  
})

app.listen(3000);

Then when we make a request to the/ route with the X-Requested-With header set to XMLHttpRequest , we get back true .

Conclusion

There’re many properties in the request object to get many things.

We can get signed cookies with the Cookie Parser middleware. Query strings and URL parameters can access in various form with query , params , and route properties.

Also, we can get parts of the subdomain with the subdomains property.

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.