Computed Vs Methods Vs Watch

Computed Properties allows you to define auto calculated properties based on other properties. For example, you could have properties firstName and lastName, from which you could create a new property, fullName, which gets updated each time either firstName or lastName changes. For example,

 data() {
    return {
      firstName: "",
      lastName: "",
    };
  },
  computed: {
    FullName: function() {
      return this.firstName.concat(this.lastName);
    },
  }

The FullName property would be recomputed each time firstName or lastName changes. You could now use the FullName property just as if you it was a normal property.

<div>FirstName :{{ firstName }}</div>
<div>LastName :{{ lastName }}</div>
<div>FullName:{{ FullName }}</div>

Computed Property Vs Method

You would why a computed property and why not a method ? For example, you could achieve the above with following.

GetFullName() {
      return this.firstName + " " + this.lastName;
    },

This could be consumed from your code as following

<div>FirstName :{{ firstName }}</div>
<div>LastName :{{ lastName }}</div>
<div>FullName:{{ GetFullName() }}</div>

So what is the difference ? Well the difference lies in the fact that the Computed Properties are cached internally, which the methods are recalculated each time, even if the corresponding property doesn’t change.

For demonstration, let us add another property to our component, age.

export default {
  name: "Home",
  data() {
    return {
      firstName: "",
      lastName: "",
      age: 0,
    };
  },
}

The properties are bound to input boxes as the following.

<div class="row">
  <div class="col-12 border py-3 bg-light">
    Inputs :
    <input v-model="firstName" placeholder="First Name" class="mx-2" />
    <input v-model="lastName" placeholder="Last Name" class="mx-2" />
    <input v-model="age" placeholder="Age" class="mx-2" />
  </div>
</div>

We will also define couple of computed properties and methods which would consumed in our code else where.

  computed: {
    ComputedFullName: function() {
      console.log("Calling Computed Full Method");
      return this.firstName + " " + this.lastName;
    },
    ComputedAge: function() {
      console.log("Calling Computed Age Method");
      return this.age + "Yrs";
    },
  },
  methods: {
    GetFullName() {
      console.log("Calling FullName Method");
     return this.firstName + " " + this.lastName;
    },
    GetAge() {
      console.log("Call Age Method");
      return this.age + "Yrs";
    },
  },

As you could observe, we have declared two computed properties, namely, ComputedFullName and ComputedAge. We also have a corresponding pair of methods namely GetFullName and GetAge.

We will use these properties and methods to display the values as following based on the input elements defined earlier.

<div class="row g-2">
  <div class="col-4 border">
    <div><b>Computed</b></div>
    <div>FirstName :{{ firstName }}</div>
    <div>LastName :{{ lastName }}</div>
    <div>FullName:{{ ComputedFullName }}</div>
    <div>Age:{{ ComputedAge }}</div>
  </div>
  <div class="col-4 border">
    <div><b>Methods</b></div>
    <div>FirstName :{{ firstName }}</div>
    <div>LastName :{{ lastName }}</div>
    <div>FullName:{{ GetFullName() }}</div>
    <div>Age:{{ GetAge() }}</div>
  </div>
</div>

Let us now build and run our application and observe how it behaves.

Type a single character in the First Name input element and observe the console window.

Calling Computed Full Method
Calling FullName Method
Call Age Method

Since the firstName changes, the ComputedFullName property is called. So is the GetFullName method. These are pretty much desired and expected.

However, you could also observe that despite no changes to the age input element (and hence age property), the GetAge() method has been invoked. That is not the case with ComputedAge property. This is because, the Calculated property would be reevaulated only if the reactive dependency changes. If the reactive depencency does not change, the cached value is retrieved by the computed property, which reevaluting the property again.

On other hand, the method would be reevaluted each time it is invoked, irrespective of any changes to the dependend properties.

Computed Vs Watched Properties

If you want to your vue application to react to a change in a certain property, you have the option to use Watch properties.

But wait, does that sound similar to computed property. Yes and No – the watched properties observe a particular property in component and react (invokes a call back) to the change. This could be used to recalculate fields, which has same effect as the computed method. Since the watch is executed only when a property changes, it does share the issue of being reevaluated unnecessarly, as with methods.

For example, let us write the watch for age property.

  data() {
    return {
      firstName: "",
      lastName: "",
      age: 0,
      ageString: "",
    };
  },
    watch: {
    age: function(value) {
      console.log("Watch Age : " + value);
      this.ageString = value + "Yrs";
    },
  },

The application would react to any changes to age property. In our call back in the given example, we are recalculating a property named ageString for each change in age. You might wonder how is it different from computed property and when you would hesistate to use the watch property.

In fact, I should stop calling it watch property. Watch is a call back, a reaction to a change. This as such doesn’t expose any property. You need to do that yourself. Computed Property in contrast is a property by definition and reacts to changes to the reactive dependencies. In the cases, it might be a good idea to use computed property. The reason is obvious if you were to complete the example by providing a watch to calculate the full name.

data() {
    return {
      firstName: "",
      lastName: "",
      age: 0,
      fullName: "",
      ageString: "",
    };
  },
  watch: {
    firstName: function(value) {
      console.log("Watch FirstName : " + value);
      this.fullName = value + " " + this.lastName;
    },
    lastName: function(value) {
      console.log("Watch LastName : " + value);
      this.fullName = this.firstName + " " + value;
    },
    age: function(value) {
      console.log("Watch Age : " + value);
      this.ageString = value + "Yrs";
    },
  },

As you can observe, since a single watch would be observing a single property, you would need to define two watches to react to changes to both first name and last name. This would, as seen in the example above, result in duplicate code. This could be easily avoided by using `calculated properties.

As you would have observed, you could basically achieve the results with any of the above options. But the hidden implications are evident once your application grows and for the same reason, it is important to understand the subtle differences to ensure you use the right feature for your requirement.

Complete source code of the post could be accessed in my Github

Axios Interceptors and Exception Handling

Handling exceptions globally and gracefully is essential part of any application. This reduces the scattered try-catch cases and enable to handle everything from one point.

In this article, we will explore how to implement global exception handling when making Api calls in an SPA design. We will use VueJs for demonstration along with Axios packages to assist the Http calls.

Axios Interceptors

Interceptors in axios provide a great oppurtunity to handle responses at a single point. Interceptors are methods which is invoked for every axios request and hence, allows you to intercept and transform the response before it makes its way to calling method.

To begin with, let us head over to our main.js and import axios

import axios from "axios";

Axios exposes two types of interceptors, one each for request and response.

Response Interceptor

For our purpose, we need the response interceptor (we will breifly speak about the request interceptor later). Axios invokes the response interceptor after the request has been send and response recieved. You could intercept this response using axios.interceptors.response.use, modify it to suit your needs before sending it back to the calling method.

axios.interceptors.response.use(
  (response) => successHandler(response),
  (error) => exceptionHandler(error)
);

The method accepts two parameters (second one is optional), each corresponding to a valid and error Response, which would be invoked depending on whether the request has succeeded or failed.

Let us plugin our interceptor in main.js to intercept the errors.

axios.interceptors.response.use(
  (response) => {
    return response;
  },
  (error) => {
    switch (error.response.status) {
      case 401:
        // Handle Unauthorized calls here
        // Display an alert
        break;
      case 500:
        // Handle 500 here
        // redirect
        break;
      // and so on..
    }

    if (error.response.status == 400) {
    }
    return Promise.reject(error);
  }
);

I ususually handle my BadRequst calls within the component. I could hence write a special response in the switch case for Error Code 400, which does the same for me.

Modifying the switch case,

switch (error.response.status) {
  case 400:
    return {
      data: null,
      hasError: true,
      error: [error.response.data],
    };
  case 401:
    // Handle Unauthorized calls here
    // Display an alert
    break;
  case 500:
    // Handle 500 here
    break;
  // and so on..
}

As seen, the interceptors provides us a global platform the handle exceptions.

Request Interceptor

A word about the request interceptor before signing off – The request interceptors are called each time before the request is made.

This provides an great oppurtunity to inject/modify headers to include authentication tokens. For example,

axios.interceptors.request.use((request) => {
   const header = getHttpHeader(); // get your custom http headers with auth token
  request.headers = header;
  return request;
});

The interceptors could be also used to show busy indicators while the request is being processed as both request interceptor and response interceptor provies us a window of oppurtunity to display a indicator before the request is send out and hide the indictor as soon as the response is recieved.

Hope that was useful.

Private Routes using VueJs

Quite often in your application, you could come across when certain pages/routes could be accessed by only authenticated users. And then there are other pages, which could be access be any one.

I tend to call them by private routes and public routes. Private Routes requires a certain condition to be met, for example, the user needs to be authenticated. We could also have additional conditions like the user needs to have a certain privilege. If the condition is not met, the user attempting to navigate to the private route needs to be redirected to a common route, usually in public route.

In VueJs, the Navigation guards allows you to intercept the navigations and conditionally evaluate whether or not to accept the redirection or cancel it. While there are multiple ways to intercept the navigation process, per-route, in-component, the easiest way would be to use the the Global Guards.

Global Before Guards

The beforeEach guard method is probably the most common approach to handle navigations. The method is called each time when a new navigation starts.

You could add the validation code in the beforeEach method to ensure only the validated users access the pages.

const router = new VueRouter({
  routes,
});

router.beforeEach((to, from, next) => {
   // Your validation logic goes here.
});


The beforeEach Method accepts 3 parameters.

  • to : The future Route
  • from : the current Route
  • next : a function that should be called to resolve the route successfully.

Real World Scenario

Let us consider a real world scenario. You have couple of routes in your application.

const routes = [
  {
    path: "/",
    name: "Default",
    component: Default
  },
  {
    path: "/login",
    name: "Login",
    component: Login
  },
  {
    path: "/dashboard",
    name: "Dashboard",
    component: Dashboard
  },
];

Ideally, you would like the Default and Login to be accessed by anyone. However, the Dashboard should be accessed only by authenticated users only.

We begin by including this very bit of logic in our route definition. We could use the meta tags for including additional information. Redefining our routes now,

const routes = [
  {
    path: "/",
    name: "Default",
    component: Default,
    meta: {
      requiresAuth: false,
    },
  },
  {
    path: "/login",
    name: "Login",
    component: Login,
    meta: {
      requiresAuth: false,
    },
  },
  {
    path: "/dashboard",
    name: "Dashboard",
    component: Dashboard,
    meta: {
      requiresAuth: true,
    },
  },
];

As you can observe, we have added a requiresAuth flag within the meta information of routes. With this in place, we could now alter our beforeEach code as following.

router.beforeEach((to, from, next) => {
  if (to.matched.some((record) => record.meta.requiresAuth)) {
    if (isAuthenticated()) {
      next();
    } else {
      next("/");
    }
  } else {
    next();
  }
});

The method now checks if the to route has the meta information flag of requiresAuth set to true and if so, calls your custom isAuthenticated method to verify if the user is authenticated to access the page.

If the user is authenticated to access the page, the next() method is called to complete the navigation successfully. Otherwise, you override the to route and navigate away to a custom route, in this case using next(“/”).

That’s all your require for creating private routes using VueJs. If you would like to see the complete code, you could find the same here in my Github.