Here is the second article in our series, where we delve into the LWC basics. In the previous article, we discussed the basic principles and structure of LWC components. Today we will talk about LWC markup.
First of all, what is LWC markup? LWC is a component-based development model where each component consists of two main parts: markup (HTML) and controller (JavaScript). Markup defines how the component is displayed on the page, while JavaScript defines the component's behavior. In this article, we won't discuss FrontEnd development but will only explore a few aspects of LWC markup.
So, how does the interaction between markup and JavaScript in LWC work? There are several ways.
Let's start by understanding the use of directives. Directives are special HTML attributes that tell Lightning Web Components what to do with an element. Directives are used in markup to pass information to JavaScript. For example, the change directive tells LWC which JavaScript function to call when the value of an input field changes.
The concept of directives in LWC is that we can use HTML attributes with special names instructing the component on what to do with a particular element. This allows for the change in the behavior and display of the component based on the values passed through these attributes.
Directives for conditional elements rendering
"lwc:if", "lwc:elseIf", and "lwc:else" - these directives are used for conditional rendering of elements. For example, we can use "lwc:if" to display elements on the page only if a certain condition is met. For example:
<template>
<template lwc:if={showGreeting}>
<p>Hello, World!</p>
</template>
</template>
In this example, if the showGreeting variable has a value of true, the <p> element will be displayed on the page.
It's important to note that when you use "lwc:if" in a template tag, it means that all content within that tag will be added to the DOM when the specified condition is met and removed from the DOM when the condition is not met. For example:
<template lwc:if={shouldRender}>
<p>This text will be added to the DOM only if shouldRender is true.</p>
</template>
In this example, if the shouldRender variable has a value of true, the <p> element will be added to the DOM and displayed on the page. If the value of shouldRender is false, the <p> element will be removed from the DOM and will not be displayed on the page.
On the other hand, you can also use the CSS hidden attribute, for example, the standard slds-hidden. This means the element remains in the DOM but becomes invisible to the user. For example:
<div class=”slds-hidden”>
<p>This text will be hidden if shouldRender is false.</p>
</div>
In this example, the <div> element and the <p> element will be added to the DOM and will remain there even if we don't see the element. It will only be hidden from the user.
So, when you use "lwc:if", elements are added and removed from the DOM according to the current state of the variable, and when you use CSS, the element remains in the DOM but can be hidden using the hidden attribute. Consider these features when developing your components. For example, you may prefer "lwc:if" in cases where you want to display data from an object on your markup that will be formed in JavaScript after certain user actions. When using CSS, this element will enter the DOM and try to get data from an object that is still undefined at that moment, which will result in an error.
So, using "lwc:if" and CSS to hide elements from the user can be helpful in various cases, depending on the component's needs. Both approaches can be used for conditional rendering of elements on the page; however, they have different approaches to manipulating the DOM, which can affect the efficiency and performance of the component.
It's also worth noting that there is a directive "if:true", but Salesforce does not recommend using them as they plan to discontinue their support and eventually remove them in the future.
Directives for iterating in markup "for:each"
Next, let's look at "for:each". This is a directive in LWC that allows repeating one or more HTML elements for each element in an array or object in a list. This directive is useful for displaying lists of data on the page and other needs, such as when the same part of the page can be repeated several times - we can build a basic small component and dynamically call it the required number of times from the parent.
Using the "for:each" directive consists of two steps:
Assign a variable in the template representing each element of the array or object.
Specify which template element should be repeated for each element of the array or object.
Here's an example of using the "for:each" directive to display a list of items:
JS
@track listItems= [
{Id: 1, Name: 'John Doe'},
{Id: 2, Name: 'Jane Smith'},
{Id: 3, Name: 'Bob Johnson'}
];
HTML
<template>
<ul>
<template for:each={listItems} for:item="item">
<li key={item.id}>{item.name}</li>
</template>
</ul>
</template>
In this example, we use the for:each directive to repeat the <li> HTML element for each element in the listItems array. The for:item variable specifies which template variable will represent each array element.
In addition, we use the key attribute to specify a unique identifier for each element. This helps to maintain the state of elements when the data list changes.
Also, the "for:each" directive can be used with objects. In this case, the "for:key" directive is used instead of the "key" attribute to specify the field that contains a unique identifier for each object.
<template>
<ul>
<template for:each={objectList} for:item="key">
<li for:key={key}>{objectList[key]}</li>
</template>
</ul>
</template>
In this example, we use the "for:each" directive to iterate over the HTML element <li> for each key in the "objectList" object.
You can also use the "for:each" directive with nested lists, where an array contains objects that, in turn, contain arrays.
<template>
<ul>
<template for:each={listItems} for:item="item">
<li key={item.id}>
{item.name}
<ul>
<template for:each={item.subitems} for:item="subitem">
<li key={subitem.id}>{subitem.name}</li>
</template>
</ul>
</li>
</template>
</ul>
</template>
In this example, we use "the for each" directive twice - to iterate over the list of parent items and the list of nested elements for each parent item. We also use the "key" attribute for each item to maintain the state of items when the data list changes.
The "for:each" directive allows you to use conditions to display items in the list. For example, in the following example, we display only the items in the list that have "isSelected" set to true:
<template>
<ul>
<template for:each={listItems} for:item="item">
<template lwc:if={item.isSelected}>
<li key={item.id}>{item.name}</li>
</template>
</template>
</ul>
</template>
In this example, we use the "lwc:if" directive within a template that is used with the "for:each" directive. This allows us to display only those list elements for which the "isSelected" property equals true.
So, the "for:each" directive is a powerful tool in LWC that makes it easy to display data lists on a page and allows you to use conditions to display specific list elements.
Event Directives in Lightning Web Components
Event directives in LWC enable you to add event handlers to elements in your component. When a specific event occurs, such as a button click, text input, or loss of focus, the registered handler is called, allowing you to perform certain actions or change the component's state.
<template>
<lightning-button onclick={handleClick}>Click me!</lightning-button>
</template>
In this example, we add an event handler, "handleClick," which is called when a user clicks the button. This is one of the most common event directives, but there are many event directives available in LWC, each with its unique features. Event directives can also depend on the type of HTML tag you are using. While we won't delve into all of them in detail here, it's recommended to refer to the documentation for a list of all available lightning tags for LWC and their detailed descriptions, including some special event directives.
Here are some tips for using event directives effectively:
Use clear and informative event handler names: Give your event handlers names that clearly indicate what they do. For example, use "handleInputChange" or "handleButtonClick" instead of generic names like "handleEvent" or "onEvent."
Separate logic: Create separate functions to handle different events to keep your component easy to understand and maintain.
Consider performance: If you're working with many elements with event handlers, you may need to address performance concerns. Try to minimize unnecessary event handlers or optimize their performance if possible.
Use documentation: Consult the LWC documentation to learn about available event directives and their properties. You can discover additional features and options that can enhance your components.
Now, let's talk about data binding.
Data Binding
Data binding is the process of linking properties of a JavaScript object with elements in the markup. When the value of a JavaScript object property changes, it automatically updates the corresponding value in the markup, and vice versa. To reference a JavaScript variable in the markup, you use the variable name enclosed in curly braces. For example, if you have a "name" variable in your JS file, you can reference it in your markup like this:
<template>
<div>Hello, {name}!</div>
</template>
In this example, the value of the "name" variable will be displayed in the markup, and if it changes, it will update on the page.
Now, let's discuss styles in LWC.
Styling in Lightning Web Components
Styling is an essential part of any front-end framework, including LWC. You can apply styles using CSS classes or direct style marking in tags. LWC also provides a set of style classes based on the Salesforce Lightning Design System (SLDS), which you can use to style your components.
One of the primary advantages of using SLDS style classes is that they ensure a consistent appearance across all Salesforce applications. This helps ensure that LWC components seamlessly integrate with other Salesforce interface elements. To use SLDS classes, add the appropriate class names to your HTML elements. For example, to style a button as the primary style, you can use the "slds-button slds-button_brand" classes:
<lightning-button variant="brand" label="Click me!" class="slds-m-top_small"></lightning-button>
In this example, the "slds-m-top_small" class is used to add a margin above the button. You can read more about SLDS styles in this article.
Apart from SLDS style classes, LWC also provides various Lightning input and button components that you can use to create forms and other interface elements. These components include <lightning-input>, <lightning-combobox>, <lightning-textarea>, <lightning-button>, and many others. These components offer a consistent appearance and are designed to work seamlessly with other Salesforce interface components.
It's essential to note that LWC components and SLDS style classes are not identical to their native HTML and CSS counterparts. While they may have similar names and functionalities, they are specifically designed for use on the Salesforce platform. This means there might be some differences in behavior and appearance compared to native HTML and CSS. Additionally, some features available in native HTML and CSS may not be available in LWC.
To sum up
In summary, we've covered the basics of LWC markup and communication between markup and JavaScript. We've shown how to use iteration, conditional operators, and variable references from JavaScript in the markup. These tools will help you create powerful and efficient Lightning Web Components components that interact with data on the page and provide a high-quality user experience.
In the next article, we'll dive into communication between LWC components, exploring the methods, advantages, disadvantages, and limitations.
Salesforce is our superpower
Be my guest to talk about your challenges and goals on a free Salesforce Advisory Demo.
Comments