DZone
Thanks for visiting DZone today,
Edit Profile
  • Manage Email Subscriptions
  • How to Post to DZone
  • Article Submission Guidelines
Sign Out View Profile
  • Post an Article
  • Manage My Drafts
Over 2 million developers have joined DZone.
Log In / Join
Refcards Trend Reports
Events Video Library
Refcards
Trend Reports

Events

View Events Video Library

Related

  • Embed a Spreadsheet Into Your Web App
  • Designing Java Web Services That Recover From Failure Instead of Breaking Under Load
  • Enhance User Experience With a Formatted Credit Card Input Field
  • Bridging JavaScript and Java Packages: An Introduction to Npm2Mvn

Trending

  • A Deep Dive into Tracing Agentic Workflows (Part 1)
  • Retesting Best Practices for Agile Teams: A Quick Guide to Bug Fix Verification
  • Why AI-Generated Code Breaks Your Testing Assumptions
  • Run Gemma 4 on Your Laptop: A Hands-On Guide to Google's Latest Open Multimodal LLM
  1. DZone
  2. Coding
  3. Languages
  4. Decorators and Mixins in Lightning Web Components

Decorators and Mixins in Lightning Web Components

Lightning Web Components, decorators, and mixins. This article is a brief analysis and tutorial of these components and how they work with Salesforce.

By 
Michael Bogan user avatar
Michael Bogan
DZone Core CORE ·
Jun. 08, 21 · Analysis
Likes (2)
Comment
Save
Tweet
Share
11.4K Views

Join the DZone community and get the full member experience.

Join For Free

It's safe to say that every modern web application these days relies to some degree on three foundational web standards: HTML, CSS, and JavaScript. While HTML has largely stabilized since the HTML5 standard, both CSS and JavaScript continue to evolve to meet developers' and users' needs.

The evolving nature of these three technologies has lead to the introduction of web components, a cross-browser solution for building complex web apps. On top of this open source standard, Salesforce developed Lightning Web Components (LWC) as a fast, enterprise-grade wrapper around vanilla web components. The result is a thin, performant, and feature-packed framework built entirely on the open web.

LWC is not only built on top of the ECMAScript standard, it also provides some nifty syntactic sugar that can transpile into standard JavaScript. Because of this, the LWC framework is able to incorporate proposed language features, which simplifies app development by future proofing your code in the always evolving JavaScript ecosystem. In this post, we'll take a closer look at two relatively recent features—mixins and decorators—and see how they can be used in your LWC apps.

What is a Mixin?

In many object-oriented programming languages, classes can "receive" additional methods through a feature called inheritance. For example, if you have a Vehicle class with the methods go and stop, subclasses like Bicycle and Car can implement them directly:

Java
 




x
24


 
1
class Vehicle {
2
  void go();
3
  void stop();
4
}
5
 
          
6
class Bicycle < Vehicle {
7
  void go() {
8
    usePedal();
9
  }
10
 
          
11
  void stop() {
12
    stopPedal();
13
  }
14
}
15
 
          
16
class Car < Vehicle {
17
  void go() {
18
    useEngine();
19
  }
20
 
          
21
  void stop() {
22
    stopEngine();
23
  }
24
}


Inheritance affects the composition of an object by changing its hierarchy. Every Bicycle and Car is now also a Vehicle. But what if you merely wanted to add in common methods to objects without dealing with any parent class? That's what a mixin does.

In a JavaScript context, mixins can add behaviors to JavaScript classes, which is useful, because classes can only extend from one other class, while multiple mixins can be added to a class. Mixins take advantage of the Object.assign method, which copies all of the properties from one object onto another:

Java
 




xxxxxxxxxx
1
18


 
1
// mixin
2
let greetingsMixin = {
3
  sayHi() {
4
    alert(`Hello ${this.name}`);
5
  },
6
  sayBye() {
7
    alert(`Bye ${this.name}`);
8
  }
9
};
10
 
          
11
class User {
12
  constructor(name) {
13
    this.name = name;
14
  }
15
}
16
 
          
17
// copy the methods
18
Object.assign(User.prototype, greetingsMixin);


User can now call sayHi and sayBye natively. Per JavaScript rules, User can also inherit from just one class, while including properties and function) from any number of mixins:

Java
 




xxxxxxxxxx
1


 
1
class User extends Person {
2
  // ...
3
}
4
 
          
5
Object.assign(User.prototype, greetingsMixin);
6
Object.assign(User.prototype, someOtherMixin);


However, writing out Object.assign is somewhat akin to littering your code. What's worse is figuring out what the method is doing isn't very intuitive. Through some native JavaScript syntax, you can actually create a "subclass factory" with mixins, and declare which mixins you're using right at the top:

Java
 




xxxxxxxxxx
1


 
1
class User extends greetingsMixin(Person) {
2
  // ...
3
}


(For more information on this technique, check out this article.)

Now, User includes the greetingsMixin and inherits from the Person class, all in one line.

This technique is more than syntactical sugar: it's actually the one which LWC regularly prefers. For example, the Navigation Mixin provides methods that are useful to navigational UI elements, but ultimately, each class that includes it should also derive from a plain LightningElement:

Java
 




xxxxxxxxxx
1


 
1
import { LightningElement } from 'lwc';
2
import { NavigationMixin } from 'lightning/navigation';
3
 
          
4
export default class TestComponent extends NavigationMixin(LightningElement) {
5
  // ...
6
}


NavigationMixin provides functionality that's crucial to components dealing with navigating through pages, while LightningElement provides all the base functionality for every component. Thus, TestComponent will need to include NavigationMixin and subclass from LightningElement, and can do so in the easy-to-see, single-line format.

What is a Decorator?

Decorators are currently a proposal to add to JavaScript, but they're so incredibly useful that many frameworks already support them. In essence, a decorator is a function that can modify a class, or any of its properties and methods. That's a pretty high-level definition, so let's take a look at what that means in practice.

Suppose we have a class like this:

Java
 




xxxxxxxxxx
1
10


 
1
class User {
2
  constructor(firstName, lastName) {
3
    this.firstName = firstName;
4
    this.lastName = lastName;
5
  }
6
 
          
7
  getFullName() {
8
    return `${this.firstName} ${this.lastName}`;
9
  }
10
}


Now, any code which makes use of this class can create a user:

Java
 




xxxxxxxxxx
1


 
1
let user = new User("Jane", "Eyre");
2
user.getFullName(); // returns "Jane Eyre"


But because of the way JavaScript is designed, a developer could inadvertently change the getFullName method if they so desired:

Java
 




xxxxxxxxxx
1


 
1
let user = new User("Jane", "Eyre");
2
user.prototype.getFullName = function() {
3
  return "not the name!;"
4
}
5
user.getFullName(); // returns "not the name!"


Now, this is obviously a trite example, but the danger still remains. You can write code to make a class property read-only, like this:

Java
 




xxxxxxxxxx
1


 
1
Object.defineProperty(User.prototype, 'gettFullName', {
2
  writable: false
3
});


This works, but it's obviously cumbersome to write for multiple properties.

Enter decorators. You can define a decorator function to apply any behavior you want to a target property. For example, to set a target as writable: false, you could do this:

Java
 




xxxxxxxxxx
1


 
1
function readonly(target) {
2
  target.descriptor.writable = false;
3
  return target;
4
}


We just defined a decorator called readonly which, when passed a target, sets its descriptor.writable property to false. This can be applied to our User class like this:

Java
 




xxxxxxxxxx
1


 
1
class User {
2
  // ...
3
  @readonly
4
  getFullName() {
5
    return `${this.firstName} ${this.lastName}`;
6
  }
7
}


Voila! The same functionality, in a single line of code.

LWC provides several decorators for developers to use. They are:

  • @api: by default, every property is hidden and private. @api exposes it publicly.
  • @track: this marks a property as reactive, which means that when its value changes, the web component will re-render and display the new value.
  • @wire: this is a decorator which signifies that we want to read Salesforce data.

These three decorators, which are unique to LWC, aim to help reduce rewriting the same code while easily providing common functionality.

Conclusion

Since LWC is built on web standards, it can leverage native APIs and languages in order to make developers immediately productive, since they're using existing skills rather than learning proprietary techniques.

If you'd like to take a closer look at Lightning Web Components, Salesforce has a boilerplate app that's built in TypeScript. There's also a Trailhead lesson to help you learn about web components in less than an hour. Or, feel free to check out the LWC dev docs for more specific reference information.

Web application Lightning (software) Java (programming language) JavaScript Property (programming)

Opinions expressed by DZone contributors are their own.

Related

  • Embed a Spreadsheet Into Your Web App
  • Designing Java Web Services That Recover From Failure Instead of Breaking Under Load
  • Enhance User Experience With a Formatted Credit Card Input Field
  • Bridging JavaScript and Java Packages: An Introduction to Npm2Mvn

Partner Resources

×

Comments

The likes didn't load as expected. Please refresh the page and try again.

  • RSS
  • X
  • Facebook

ABOUT US

  • About DZone
  • Support and feedback
  • Community research

ADVERTISE

  • Advertise with DZone

CONTRIBUTE ON DZONE

  • Article Submission Guidelines
  • Become a Contributor
  • Core Program
  • Visit the Writers' Zone

LEGAL

  • Terms of Service
  • Privacy Policy

CONTACT US

  • 3343 Perimeter Hill Drive
  • Suite 215
  • Nashville, TN 37211
  • [email protected]

Let's be friends:

  • RSS
  • X
  • Facebook