CustomEvent()
constructor. To dispatch an
event, call the EventTarget.dispatchEvent()
method.The CustomEvent()
constructor has one required
parameter, which is a string indicating the event type. As a component author, you name
the event type when you create the event. You can use any string as your event type.
However, we recommend that you conform with the DOM event standard.
- No uppercase letters
- No spaces
- Use underscores to separate words
Don’t prefix your event name with the string on
,
because inline event handler names must start with the string on
. If your event is called onmessage
,
the markup would be <c-my-component ononmessage={handleMessage}>
. Notice the doubled word onon
, which is confusing.
Let’s jump into some code.
The c-paginator
component contains
Previous and Next buttons. When a user
clicks the buttons, the component creates and dispatches previous
and next
events. You can drop
the paginator
component into any component that needs
Previous and Next buttons. That parent
component listens for the events and handles
them.
<!-- paginator.html -->
<template>
<lightning-layout>
<lightning-layout-item>
<lightning-button label="Previous" icon-name="utility:chevronleft" onclick={previousHandler}></lightning-button>
</lightning-layout-item>
<lightning-layout-item flexibility="grow"></lightning-layout-item>
<lightning-layout-item>
<lightning-button label="Next" icon-name="utility:chevronright" icon-position="right" onclick={nextHandler}></lightning-button>
</lightning-layout-item>
</lightning-layout>
</template>
When a user clicks a button, the previousHandler
or nextHandler
function executes. These
functions create and dispatch the previous
and
next
events.
// paginator.js
import { LightningElement } from 'lwc';
export default class Paginator extends LightningElement {
previousHandler() {
this.dispatchEvent(new CustomEvent('previous'));
}
nextHandler() {
this.dispatchEvent(new CustomEvent('next'));
}
}
These events are simple “something happened” events. They don’t pass a data payload up the DOM tree, they simply announce that a user clicked a button.
Let’s drop paginator
into a component called c-event-simple
, which listens for and handles the previous
and next
events.
To listen for events, use an HTML attribute with the syntax oneventtype
. Since our event types are previous
and next
,
the listeners are onprevious
and onnext
.
<!-- eventSimple.html -->
<template>
<lightning-card title="EventSimple" icon-name="custom:custom9">
<div class="slds-m-around_medium">
<p class="slds-m-vertical_medium content">Page {page}</p>
<c-paginator onprevious={previousHandler} onnext={nextHandler}></c-paginator>
</div>
</lightning-card>
</template>
When c-event-simple
receives the previous
and next
events, previousHandler
and nextHandler
increase and decrease the page
number.
// eventSimple.js
import { LightningElement } from 'lwc';
export default class EventSimple extends LightningElement {
page = 1;
previousHandler() {
if (this.page > 1) {
this.page = this.page - 1;
}
}
nextHandler() {
this.page = this.page + 1;
}
}
c-event-simple
component and the
c-paginator
component in the github.com/trailheadapps/lwc-recipes repo.Pass Data in an Event
To pass data up to a
receiving component, set a detail
property
in the CustomEvent
constructor. Receiving
components access the data in the detail
property in the event listener’s handler function.
CustomEvent
interface imposes no type requirements or structure on the detail
property. However it’s important to
send only primitive data. JavaScript passes all data types by reference except
for primitives. If a component includes an object in its detail
property, any listener can mutate
that object without the component’s knowledge. This is a bad thing! It’s a best
practice either to send only primitives, or to copy data to a new object before
adding it to the detail
property.
Copying the data to a new object ensures that you’re sending only the data you
want, and that the receiver can’t mutate your data. Let’s look at the c-event-with-data
component
from the lwc-recipes repo.
Each item in the list of contacts is a nested c-contact-list-item
component.
The c-contact-list-item
component wraps the contact name and picture in an
anchor tag with an onclick
event listener that
executes the selectHandler
function.
<!-- contactListItem.html -->
<template>
<a href="#" onclick={selectHandler}>
<lightning-layout vertical-align="center">
<lightning-layout-item>
<img src={contact.Picture__c}></img>
</lightning-layout-item>
<lightning-layout-item padding="around-small">
<p>{contact.Name}</p>
</lightning-layout-item>
</lightning-layout>
</a>
</template>
When a user clicks to select a contact, the component creates and dispatches a
CustomEvent
called selected
. The event includes the data detail: this.contact.Id
, which is the ID of the
selected contact. The parent, c-event-custom
,
uses the contact reference to display more information about the
contact.
// contactListItem.js
import { LightningElement, api } from 'lwc';
export default class ContactListItem extends LightningElement {
@api contact;
selectHandler(event) {
// Prevents the anchor element from navigating to a URL.
event.preventDefault();
// Creates the event with the contact ID data.
const selectedEvent = new CustomEvent('selected', { detail: this.contact.Id });
// Dispatches the event.
this.dispatchEvent(selectedEvent);
}
}
The
c-event-with-data
component listens for the
selected
event in the onselected
attribute and handles it in the contactSelected
event handler.
<!-- eventWithData.html -->
<template>
<lightning-card title="EventWithData" icon-name="custom:custom9">
<lightning-layout class="slds-m-around_medium">
<lightning-layout-item>
<template if:true={listIsNotEmpty}>
<template for:each={contacts.data} for:item="contact">
<c-contact-list-item key={contact.Id} contact={contact} onselected={contactSelected}></c-contact-list-item>
</template>
</template>
</lightning-layout-item>
<lightning-layout-item class="slds-m-left_medium">
<template if:true={selectedContact}>
<img src={selectedContact.Picture__c}></img>
<p>{selectedContact.Name}</p>
<p>{selectedContact.Title}</p>
<p><lightning-formatted-phone value={selectedContact.Phone}></lightning-formatted-phone></p>
<p><lightning-formatted-email value={selectedContact.Email}></lightning-formatted-email></p>
</template>
</lightning-layout-item>
</lightning-layout>
</lightning-card>
</template>
In the contactSelected
event handler, the
component assigns the event.detail
property to
the contactId
property. It finds the contact
with that ID in the contacts
array provisioned
via @wire
, and displays the contact’s name,
title, phone, and email in the
template.
// eventWithData.js
import { LightningElement, wire } from 'lwc';
import getContactList from '@salesforce/apex/ContactController.getContactList';
export default class EventWithData extends LightningElement {
selectedContact;
@wire(getContactList) contacts;
contactSelected(event) {
const contactId = event.detail;
this.selectedContact = this.contacts.data.find(contact => contact.Id === contactId);
}
get listIsNotEmpty() {
return this.contacts && Array.isArray(this.contacts.data) && this.contacts.data.length > 0;
}
}
No comments:
Post a Comment