Sign Up

Sign Up to our social questions and Answers Engine to ask questions, answer people’s questions, and connect with other people.

Have an account? Sign In

Have an account? Sign In Now

Sign In

Login to our social questions & Answers Engine to ask questions answer people’s questions & connect with other people.

Sign Up Here

Forgot Password?

Don't have account, Sign Up Here

Forgot Password

Lost your password? Please enter your email address. You will receive a link and will create a new password via email.

Have an account? Sign In Now

Sorry, you do not have permission to ask a question, You must login to ask a question.

Forgot Password?

Need An Account, Sign Up Here

Please type your username.

Please type your E-Mail.

Please choose an appropriate title for the post.

Please choose the appropriate section so your post can be easily searched.

Please choose suitable Keywords Ex: post, video.

Browse

Need An Account, Sign Up Here

Please briefly explain why you feel this question should be reported.

Please briefly explain why you feel this answer should be reported.

Please briefly explain why you feel this user should be reported.

Sign InSign Up

Querify Question Shop: Explore Expert Solutions and Unique Q&A Merchandise

Querify Question Shop: Explore Expert Solutions and Unique Q&A Merchandise Logo Querify Question Shop: Explore Expert Solutions and Unique Q&A Merchandise Logo

Querify Question Shop: Explore Expert Solutions and Unique Q&A Merchandise Navigation

  • Home
  • About Us
  • Contact Us
Search
Ask A Question

Mobile menu

Close
Ask a Question
  • Home
  • About Us
  • Contact Us
Home/ Questions/Q 4190

Querify Question Shop: Explore Expert Solutions and Unique Q&A Merchandise Latest Questions

Author
  • 61k
Author
Asked: November 26, 20242024-11-26T09:40:10+00:00 2024-11-26T09:40:10+00:00

Web Components Communication Using an Event Bus

  • 61k

Imagine you're building a Single Page Application using Web Components only. You have several pages, have configured the routes, and need to be able to handle general events or actions.

Here's when you start to think about potential solutions as well: Maybe it's time to add state management to the application? Is it a good time to build a “custom” solution? What about using some design patterns in this case?

The answers to these questions will depend on the complexity of the current scenario, the experience of the developers, or on the opinions of the team. It is clear that there is no absolute answer!

In this article, we'll go over how to communicate between components using a custom Event Bus implementation.

What is an Event Bus?

The Event Bus idea is generally associated with the Publish-subscribe pattern:

Publish–subscribe is a messaging pattern where senders of messages, called publishers, do not program the messages to be sent directly to specific receivers, called 'subscribers', but instead, categorize published messages into classes without knowledge of subscribers

In other words, an Event Bus can be considered as a global way to transport messages or events to make them accessible from any place within the application.

Event Bus

Web Components Communication

When you're working with Web Components through LitElement, it's usual firing events for sending messages between them. You can use either Standard or Custom events.

  • Fire a Standard Event using new Event('event')
  • Fire a Custom Event using new CustomEvent('event', {...options})

For a practical example, let's assume we have two components at this time: The first one could be named as a parent component and the second one as the child component

The Child Component

The child component is defined as a custom button implementation only.

import { LitElement, html, property, customElement, css } from 'lit-element';  export interface MyButtonEvent {   label: string;   date: string; }  @customElement('my-button') class MyButton extends LitElement {   @property({ type: String }) label: string = 'Hello LitElement';    constructor() {     super();   }    render() {     return html`       <span @click=${this.handleClick}>         ${this.label}       </span>     `;   }    private handleClick(e: MouseEvent) {     this.dispatchEvent(new Event("myClick"));   } } 
Enter fullscreen mode Exit fullscreen mode

The above code snippet does the following:

  • It creates a model for the data to be passed through a Custom Event. The model is defined as an interface called MyButtonEvent.
  • Next, the component is created using a TypeScript class with the help of the LitElement decorators
    • The @customElement decorator allows the component definition using a name for it: my-button. It is applied at the class level.
    • The static styles attribute defines the styles for the component using a tagged template literal(css)
    • The @property decorator, which allows declaring properties in a readable way.
    • The render method returns the HTML content through a template literal(html). This function will be called any time label property changes.

Now pay attention to the render() method. It does use the @click binding into the template. And this allows capturing the click event itself in a declarative way.

The Parent Component

The parent component works as a container since it will be in charge of the custom button rendering. Here's how the template will be using the child component:

<my-button label="Show Alert"> </my-button> 
Enter fullscreen mode Exit fullscreen mode

However, in a real-world scenario, this parent component we'll need to handle the child event myClick once it gets fired.

// my-container.ts  import { LitElement, html, customElement, css } from "lit-element"; import "./my-button";  @customElement("my-container") class MyContainer extends LitElement {   static styles = css`     :host {       display: block;     }   `;    constructor() {     super();   }    render() {     return html`       <my-button @myClick=${this.handleClick} label="Hello LitElement">       </my-button>     `;   }    private handleClick(e: Event) {     console.log("MyContainer, myClick", e);   } } 
Enter fullscreen mode Exit fullscreen mode

Find a brief explanation of the previous code snippet before starting to use the Event Bus.

  • The render function defines a template literal, and makes use of the my-button element using <my-button></my-button> as if it were part of the HTML vocabulary
    • The @myClick attribute sets a function reference to handle the event in a declarative syntax.
    • The label attribute sets the text displayed in the button. Anytime it changes, the button will be rendered again.
  • The handleClick function receives an Event object with more information about it. Open your browser's console, and feel free to inspect this value.

In case you require sending data along with the event, the handleClick method can be updated accordingly:

  private handleClick(e: CustomEvent<MyButtonEvent>) {     const detail: MyButtonEvent = e.detail;     // Process the 'detail' object here   } 
Enter fullscreen mode Exit fullscreen mode

Event Bus Communication

For this example, we can assume that the parent component will act as the “root” of all events to be used through the Event Bus object.

Then, let's register an alert event in the constructor method. The purpose of it will be to render an alert message from different places in the application.

// my-container.ts  class MyContainer extends LitElement {    private alertRegistry: Registry;    constructor() {     super();      this.alertRegistry = EventBus.getInstance().register(       'alert',       (message: string) => {         AlertManager.showAlert(message);       }     );   } } 
Enter fullscreen mode Exit fullscreen mode

Once you register an event, you can get the Registry object to be able to unregister later.

You're ready to go!

As a next step, let's dispatch an alert event every time the button gets “clicked”. This can be done within the handleClick function:

  // my-container.ts   private handleClick(e: CustomEvent<MyButtonEvent>) {     const detail: MyButtonEvent = e.detail;     EventBus.getInstance().dispatch('alert', `Alert at ${detail.date}`);   } 
Enter fullscreen mode Exit fullscreen mode

Now the Event Bus is working as expected. You can start registering/dispatching other events from other components. They do not need to be related in any way, since the communication channel for this type of event will be the Event Bus.

Unregistering from the Event Bus

It's important to keep track of the different events you're registering to avoid potential memory leaks in the application.

For this example, we'll enable displaying the alert message only for the first time. Other clicks over the “Show Alert” button won't take any effect or dispatch actions through the Event Bus.

Let's update the parent component.

// my-container.ts    private handleClick(e: CustomEvent<MyButtonEvent>) {     const detail: MyButtonEvent = e.detail;      EventBus.getInstance().dispatch('alert', `Alert at ${detail.date}`);     this.alertRegistry.unregister();   } 
Enter fullscreen mode Exit fullscreen mode

The last line of the handleClick method ensures the unregistering process from the Event Bus. Thus, other calls for the alert event will be ignored.

Live Demo

Wanna play around with this code? Just open the embedded Stackblitz editor:

Conclusion

In this article, I described two ways to communicate and pass data between components.

  • In case the components are related, it is clear that the best way to communicate them is through simple or custom events.
  • If you're planning to send events across the entire application, no matter the component or the module, then the Event Bus may work for you. In other words, it's a way to just send Events to a common channel without knowing who is going to process the message at the end.

Feel free to reach out on Twitter if you have any questions. Follow me on GitHub to see more about my work. Be ready for more articles about Lit in this blog.


This Dot Labs is a modern web consultancy focused on helping companies realize their digital transformation efforts. For expert architectural guidance, training, or consulting in React, Angular, Vue, Web Components, GraphQL, Node, Bazel, or Polymer, visit thisdotlabs.com.

This Dot Media is focused on creating an inclusive and educational web for all. We keep you up to date with advancements in the modern web through events, podcasts, and free content. To learn, visit thisdot.co.

typescriptwebcomponentswebdev
  • 0 0 Answers
  • 0 Views
  • 0 Followers
  • 0
Share
  • Facebook
  • Report

Leave an answer
Cancel reply

You must login to add an answer.

Forgot Password?

Need An Account, Sign Up Here

Sidebar

Ask A Question

Stats

  • Questions 4k
  • Answers 0
  • Best Answers 0
  • Users 1k
  • Popular
  • Answers
  • Author

    How to ensure that all the routes on my Symfony ...

    • 0 Answers
  • Author

    Insights into Forms in Flask

    • 0 Answers
  • Author

    Kick Start Your Next Project With Holo Theme

    • 0 Answers

Top Members

Samantha Carter

Samantha Carter

  • 0 Questions
  • 20 Points
Begginer
Ella Lewis

Ella Lewis

  • 0 Questions
  • 20 Points
Begginer
Isaac Anderson

Isaac Anderson

  • 0 Questions
  • 20 Points
Begginer

Explore

  • Home
  • Add group
  • Groups page
  • Communities
  • Questions
    • New Questions
    • Trending Questions
    • Must read Questions
    • Hot Questions
  • Polls
  • Tags
  • Badges
  • Users
  • Help

Footer

Querify Question Shop: Explore Expert Solutions and Unique Q&A Merchandise

Querify Question Shop: Explore, ask, and connect. Join our vibrant Q&A community today!

About Us

  • About Us
  • Contact Us
  • All Users

Legal Stuff

  • Terms of Use
  • Privacy Policy
  • Cookie Policy

Help

  • Knowledge Base
  • Support

Follow

© 2022 Querify Question. All Rights Reserved

Insert/edit link

Enter the destination URL

Or link to existing content

    No search term specified. Showing recent items. Search or use up and down arrow keys to select an item.