JavaScript for LWC

The Concept of Computed Properties in Lightning Web Components (LWC)


Let's delve even deeper into the concept of computed properties in Lightning Web Components (LWC) with a more detailed explanation and an extended example.


What are Computed Properties in LWC?


Computed properties are a key feature in LWC that allow you to dynamically calculate values based on other properties and dependencies within your component. They automatically update whenever the dependent properties change, ensuring that your component stays in sync and accurate.

Key Points about Computed Properties:

1. Automatic Recalculation: Computed properties automatically recompute their values whenever the properties they depend on change. This means you don't have to explicitly call a function or method to update them.
2. Dependency Tracking: LWC keeps track of the properties that a computed property depends on. If any of those dependent properties change, the computed property is automatically updated.
3. Read-Only: Computed properties are read-only. They are derived values and cannot be directly modified. Instead, they change automatically based on their dependencies.


Why Use Computed Properties?

Computed properties simplify your code by abstracting complex calculations and logic into easily readable properties. They enhance the maintainability of your components and improve performance by avoiding unnecessary recalculations.


Extended Example: Shopping Cart Total

Let's consider a scenario where you're building a simple shopping cart component. Each item in the cart has a quantity and a price, and you want to display the total cost. Computed properties are perfect for this use case.

Step 1: Create the LWC Component

Create a new LWC component called `shoppingCart`.

Step 2: Write the HTML Markup

`shoppingCart.html`:



Step 3: Write the JavaScript Logic

`shoppingCart.js`:

import { LightningElement, track } from 'lwc';

export default class ShoppingCart extends LightningElement {
    @track items = [
        { id: 1, name: 'Item A', price: 10, quantity: 1, total: 10 },
        { id: 2, name: 'Item B', price: 15, quantity: 2, total: 30 },
        { id: 3, name: 'Item C', price: 5, quantity: 3, total: 15 }
    ];

    // Computed property for calculating the cart total
    get cartTotal() {
        return this.items.reduce((total, item) => total + item.total, 0);
    }

    // Event handler for quantity change
    handleQuantityChange(event) {
        const itemId = event.target.closest('li').key;
        const selectedItem = this.items.find(item => item.id === itemId);
        selectedItem.quantity = parseInt(event.target.value);
        selectedItem.total = selectedItem.quantity * selectedItem.price;

        // Trigger reactivity by creating a new copy of the items array
        this.items = [...this.items];
    }
}

Explanation of the Code:

1. In the HTML markup, we loop through each item in the `items` array and display its name, quantity, price, and total. We also display the overall cart total.
2. In the JavaScript logic, we define the `items` array, each containing information about an item in the cart.
3. The `get cartTotal()` computed property calculates the total cost of the shopping cart by using the `reduce` function to sum up the `total` property of each item.
4. The `handleQuantityChange` method updates the quantity and total of an item when the user changes the quantity input. We trigger reactivity by creating a new copy of the `items` array using the spread operator.


What Happens?

When you change the quantity of an item, the handleQuantityChange method is called, updating the item's quantity and total. This change automatically triggers the recalculation of the cartTotal computed property, and the displayed values are updated without any further action.

Computed properties ensure that the cart total is always accurate, reflecting changes in item quantities.

Example Scenario: Simple Calculator

Imagine we're creating a simple calculator component that performs basic arithmetic operations: addition, subtraction, multiplication, and division. We'll use computed properties to dynamically display the results based on user input.

Step 1: Create the LWC Component

Create a new LWC component called `simpleCalculator`.

Step 2: Write the HTML Markup

`simpleCalculator.html`:



Step 3: Write the JavaScript Logic

`simpleCalculator.js`:

import { LightningElement, track } from 'lwc';

export default class SimpleCalculator extends LightningElement {
    @track number1 = 0;
    @track number2 = 0;

    // Computed properties
    get sum() {
        return this.number1 + this.number2;
    }

    get difference() {
        return this.number1 - this.number2;
    }

    get product() {
        return this.number1 * this.number2;
    }

    get quotient() {
        return this.number1 / this.number2;
    }

    // Event handler for input change
    handleNumberChange(event) {
        const inputName = event.target.label;
        if (inputName === 'Number 1') {
            this.number1 = parseFloat(event.target.value);
        } else if (inputName === 'Number 2') {
            this.number2 = parseFloat(event.target.value);
        }
    }
}

Explanation of the Code:

1. In the HTML markup, we use Lightning input fields to allow the user to input two numbers. We then display the computed results (sum, difference, product, and quotient) using placeholders like `{sum}`.
2. In the JavaScript logic, we define two properties `number1` and `number2` to hold the user's input.
3. For each arithmetic operation (sum, difference, product, quotient), we define a computed property using the `get` keyword. These computed properties are `sum`, `difference`, `product`, and `quotient`.
4. The `handleNumberChange` method is an event handler that updates the `number1` or `number2` properties based on user input.

What Happens?

When you input values in the Number 1 and Number 2 fields, the computed properties (`sum`, `difference`, `product`, `quotient`) automatically calculate and update their values based on the changes in the `number1` and `number2` properties. This ensures that the displayed results are always up-to-date without needing manual updates.

In this example, computed properties simplify the code and keep the component in sync, making it easier to maintain and understand.


Example: Calculating Total Price

Let's illustrate computed properties with an example of a simple product list where you can select the quantity of each product, and the total price is automatically calculated.

HTML Markup (`productList.html`):



JavaScript Logic (productList.js):

import { LightningElement, track } from 'lwc';

export default class ProductList extends LightningElement {
    @track products = [
        { id: 1, name: 'Product A', price: 10, quantity: 1 },
        { id: 2, name: 'Product B', price: 15, quantity: 2 },
        { id: 3, name: 'Product C', price: 5, quantity: 3 }
    ];

    // Computed property for calculating total price
    get totalPrice() {
        return this.products.reduce((total, product) => total + (product.price * product.quantity), 0);
    }

    // Event handler for quantity change
    handleQuantityChange(event) {
        const productId = event.target.closest('li').key;
        const selectedProduct = this.products.find(product => product.id === productId);
        selectedProduct.quantity = parseInt(event.target.value);
    }
}

In this example, the `totalPrice` computed property calculates the total price of all selected products based on their quantities. When you change the quantity of a product, the computed property `totalPrice` automatically recalculates, ensuring that the displayed total is always accurate.


Summary

Computed properties in LWC are an essential tool for building dynamic, reactive, and efficient components. They automatically update based on dependencies, making your code more maintainable and your user interface more responsive. Computed properties help encapsulate complex logic and provide a cleaner way to manage derived data in your components.