5 Real life use cases of VueJs Computed properties, with code examples.
Tags: vue, javascript, frontend, webdev
Published: 2023-05-31 15:39:29

In Vue.js, computed properties are functions that are used to calculate and return a value based on the current state of the Vue instance. They are defined in the computed property of a Vue component and can be accessed like data properties within the template or other computed properties.

Computed properties are useful when you need to perform some logic or calculations on the data and generate a derived value that can be used in the template. The computed property will be updated automatically whenever the data it depends on changes, ensuring that the value is always up to date.

Here's an example of how to define computed properties in Vue.js:

```
data() {
    return {
      firstName: 'John',
      lastName: 'Doe'
    };
  },
  computed: {
    fullName() {
      return this.firstName + ' ' + this.lastName;
    },
    reversedFullName() {
      return this.fullName.split('').reverse().join('');
    }
  }
```
In the example above, we have a component with two data properties firstName and lastName. We define two computed properties fullName and reversedFullName. The fullName computed property concatenates the first and last name, while the reversedFullName computed property reverses the characters of the fullName property.

In the template, we can then use these computed properties like regular data properties:

```
<template>
  <div>
    <p>Full Name: {{ fullName }}</p>
    <p>Reversed Full Name: {{ reversedFullName }}</p>
  </div>
</template>
```
Whenever the firstName or lastName data properties change, the fullName and reversedFullName computed properties will be re-evaluated and the template will be updated accordingly.

Computed properties provide a clean and declarative way to work with derived values in Vue.js and can help keep your code more readable and maintainable.

**

## 5 MORE REAL CASE EXAMPLES OF COMPUTED PROPERTIES.
**

**1. Shopping Cart**: Calculate the total price or quantity of items in a shopping cart based on the individual item prices and quantities.

```
<template>
  <div>
    <ul>
      <li v-for="item in cartItems" :key="item.id">
        {{ item.name }} - {{ item.price }} - Quantity: {{ item.quantity }}
      </li>
    </ul>
    <p>Total Price: {{ totalPrice }}</p>
    <p>Total Quantity: {{ totalQuantity }}</p>
  </div>
</template>

<script>
export default {
  data() {
    return {
      cartItems: [
        { id: 1, name: 'Item 1', price: 10, quantity: 2 },
        { id: 2, name: 'Item 2', price: 15, quantity: 1 },
        { id: 3, name: 'Item 3', price: 20, quantity: 3 }
      ]
    };
  },
  computed: {
    totalPrice() {
      return this.cartItems.reduce((total, item) => total + item.price * item.quantity, 0);
    },
    totalQuantity() {
      return this.cartItems.reduce((total, item) => total + item.quantity, 0);
    }
  }
};
</script>

```
In this example, we have a cartItems array that represents items in a shopping cart. The computed properties totalPrice and totalQuantity calculate the total price and total quantity of items in the cart, respectively, using the reduce() method.

The reduce() method is used with an initial value of 0 for both computed properties. It iterates over the cartItems array and accumulates the total price and quantity by multiplying the price with the quantity for each item.

**2. Form Validation:** Check if form fields meet certain validation criteria, such as required fields, maximum length, or specific patterns.

```
<template>
  <form @submit="submitForm">
    <input v-model="name" :class="{ 'is-invalid': !isNameValid }" type="text" placeholder="Name" required>
    <input v-model="email" :class="{ 'is-invalid': !isEmailValid }" type="email" placeholder="Email" required>
    <button type="submit" :disabled="!isFormValid">Submit</button>
  </form>
</template>

<script>
export default {
  data() {
    return {
      name: '',
      email: ''
    };
  },
  computed: {
    isNameValid() {
      return this.name.length > 0;
    },
    isEmailValid() {
      return /^[^\s@]+@[^\s@]+\.[^\s@]+$/.test(this.email);
    },
    isFormValid() {
      return this.isNameValid && this.isEmailValid;
    }
  },
  methods: {
    submitForm() {
      // Submit form logic
    }
  }
};
</script>

```
 this example, we have a form with name and email fields. The computed properties isNameValid, isEmailValid, and isFormValid are used for form validation.

The isNameValid computed property checks if the name field has a non-empty value. The isEmailValid computed property uses a regular expression to check if the email field has a valid email format. The isFormValid computed property checks if both the name and email fields are valid.

The CSS class is-invalid is conditionally applied to the input fields based on their validation status.

**3. Filtering and Sorting:** Compute a filtered or sorted version of a data list based on user-defined criteria, such as filtering products by category or sorting a list of tasks by priority.

```
<template>
  <div>
    <select v-model="selectedCategory">
      <option value="">All</option>
      <option v-for="category in categories" :key="category.id" :value="category.id">{{ category.name }}</option>
    </select>

    <ul>
      <li v-for="product in filteredProducts" :key="product.id">
        {{ product.name }} - {{ product.price }}
      </li>
    </ul>
  </div>
</template>

<script>
export default {
  data() {
    return {
      selectedCategory: '',
      categories: [
        { id: 1, name: 'Category 1' },
        { id: 2, name: 'Category 2' },
        { id: 3, name: 'Category 3' }
      ],
      products: [
        { id: 1, name: 'Product 1', price: 10, categoryId: 1 },
        { id: 2, name: 'Product 2', price: 15, categoryId: 2 },
        { id: 3, name: 'Product 3', price: 20, categoryId: 3 }
      ]
    };
  },
  computed: {
    filteredProducts() {
      if (this.selectedCategory) {
        return this.products.filter(product => product.categoryId === this.selectedCategory);
      } else {
        return this.products;
      }
    }
  }
};
</script>

```
In this example, we have a list of products with name, price, and categoryId properties. The computed property filteredProducts is used to filter the products based on the selectedCategory value.

The <select> element allows the user to select a category, and the v-model directive binds the selected category to the selectedCategory data property.

The filteredProducts computed property filters the products array based on the selected category. If a category is selected, only products with a matching categoryId are returned. If no category is selected, all products are returned.

**4. Pagination:** Determine the current page and number of pages based on the total number of items and items per page, enabling easy pagination navigation.

```
<template>
  <div>
    <ul>
      <li v-for="item in paginatedItems" :key="item.id">
        {{ item.name }} - {{ item.price }}
      </li>
    </ul>

    <div>
      <button @click="previousPage" :disabled="currentPage === 1">Previous</button>
      <span>Page {{ currentPage }} of {{ totalPages }}</span>
      <button @click="nextPage" :disabled="currentPage === totalPages">Next</button>
    </div>
  </div>
</template>

<script>
export default {
  data() {
    return {
      currentPage: 1,
      itemsPerPage: 3,
      items: [
        { id: 1, name: 'Item 1', price: 10 },
        { id: 2, name: 'Item 2', price: 15 },
        { id: 3, name: 'Item 3', price: 20 },
        { id: 4, name: 'Item 4', price: 25 },
        { id: 5, name: 'Item 5', price: 30 },
        { id: 6, name: 'Item 6', price: 35 },
        { id: 7, name: 'Item 7', price: 40 }
      ]
    };
  },
  computed: {
    paginatedItems() {
      const startIndex = (this.currentPage - 1) * this.itemsPerPage;
      const endIndex = startIndex + this.itemsPerPage;
      return this.items.slice(startIndex, endIndex);
    },
    totalPages() {
      return Math.ceil(this.items.length / this.itemsPerPage);
    }
  },
  methods: {
    previousPage() {
      if (this.currentPage > 1) {
        this.currentPage--;
      }
    },
    nextPage() {
      if (this.currentPage < this.totalPages) {
        this.currentPage++;
      }
    }
  }
};
</script>

```
In this example, we have a list of items with name and price properties. The computed properties paginatedItems and totalPages are used for pagination.

The paginatedItems computed property calculates the start and end indices based on the current page and items per page. It uses the slice() method to return a portion of the items array corresponding to the current page.

The totalPages computed property calculates the total number of pages by dividing the total number of items by the items per page and rounding up using Math.ceil().

The previous and next page buttons update the currentPage value, which triggers the re-computation of the paginatedItems computed property and enables navigation between pages.

**5. Conditional Styling:** Dynamically apply CSS classes or styles to elements based on certain conditions, like highlighting overdue tasks or applying different styles to completed items.

```
<template>
  <div>
    <ul>
      <li v-for="task in tasks" :key="task.id" :class="{ 'task-overdue': isOverdue(task), 'task-completed': task.completed }">
        {{ task.name }}
      </li>
    </ul>
  </div>
</template>

<script>
export default {
  data() {
    return {
      tasks: [
        { id: 1, name: 'Task 1', dueDate: '2023-06-01', completed: false },
        { id: 2, name: 'Task 2', dueDate: '2023-05-30', completed: true },
        { id: 3, name: 'Task 3', dueDate: '2023-06-02', completed: false }
      ]
    };
  },
  methods: {
    isOverdue(task) {
      const dueDate = new Date(task.dueDate);
      const today = new Date();
      return dueDate < today;
    }
  }
};
</script>

<style scoped>
.task-overdue {
  color: red;
  font-weight: bold;
}

.task-completed {
  text-decoration: line-through;
}
</style>

```
In this example, we have a list of tasks with name, dueDate, and completed properties. The isOverdue method checks if a task is overdue by comparing the due date with the current date.

The v-for directive iterates over the tasks array and applies conditional CSS classes using the :class binding. The task-overdue class is applied to tasks that are overdue, and the task-completed class is applied to completed tasks.

The scoped <style> block defines the styles for the conditional classes. Overdue tasks are displayed in red with bold font weight, and completed tasks have a line-through text decoration.



> These examples showcase the practical use of computed properties in various real-life scenarios. Feel free to use them in your projects.