-
Notifications
You must be signed in to change notification settings - Fork 10
lwc 301 api design
When designing LWCs for reusability, there are a couple of fundamental blocks of knowledge to consider:
-
@api
decorator slots
- Event Bubbling
- Declarative Tooling
First and most obvious is the existence of this decorator which can be applied to both properties
and functions
.
Note: Be careful in your public API design here, as often the choice of api names for your properties cannot be undone if they are eventually referenced in the declarative layer such as Flexipages or Screen Flows (the XML design / target configs).
The most useful resource that helped me understand how to approach reusability was looking at the base components
for inspiration. The public functions and api props can serve as inspiration on how best to approach the developer ergonomics of leveraging your custom reusable components. You can see the base-component-recipes here and as always, the component library.
Consider the following:
- How you want to reference this component from the template, so which
@api
props should help define its state. - How you want to pass data in from JS, as an alternative to
@api
props. For example, a custom@api
function that can take in parameters.
Working backwards from the developer ergonomics is often the easiest path forward, and then based on that - you can derive the implementation from a second pass. The idea here is to index more on reusability and how it would feel to interact with, either in code or some declarative layer.
The public @api
should represent the total state that can be manipulated by the [insert current and future SFDC tech] that leverages the LWC.
The second and less obvious topic for api design is the usage of markup slots
to help fine tune composition.
An easy analogy is the lightning-card
base component which has various slots
like title
, footer
, and actions
. More reading on slots here.
An example:
<!-- c-reusable-component -->
...
<slot name="composedActions" onslotchange={handleComposedActionSlotChange}></slot>
...
<!-- c-parent-component -->
<c-reusable-component>
<div slot="composedActions">
<lightning-layout>
<div class="slds-form-element">
<div class="slds-form-element__control">
...
</div>
</div>
<lightning-button
...
></lightning-button>
</lightning-layout>
</div>
</c-reusable-component>
This allows for specifying which parts of the UI on the c-reusable-component
can be defined by markup composition from a parent.
Note: This will only cover strategy, not implementation details. It assumes you've already gone through Hierarchy Communication for that information.
As a primer, please refer to this doc about event best practices. In the context of this topic, since we are discussing API design, we can assume that any events dispatched are for public consumption aka crossing the shadow boundary.
So then, it would follow suit that when designing events that carry payloads
to use the event.detail
nomenclature like so:
const payload = {
detail: {
selectedRecordId: this.selected,
selectedDisplayValue: this.inputValue
}
};
this.dispatchEvent(new CustomEvent('selected', payload));
handleSelected(event) {
console.log(event.detail.selectedRecordId);
console.log(event.detail.selectedDisplayValue);
}
As a primer, please refer to this architect decision guide on building forms to get insight on the direction SFDC is going with its declarative tooling and how LWCs can fit into those solutions.
Per the above, we know that SFDC is going to have continued investment in Screen Flows, one of the best "OOTB" solutions for dealing with multi-screen user journeys. This has replaced my need for writing wizards, and I believe you should follow suit if you can align to some of the UX quirks and limitations.
This could be an entire wiki in itself, but I'll include a few references on how to get started there:
TODO:
Note: Custom Property Editors (CPE) can get your design menu closer to how native components can be configured in a screen flow. HOWEVER I personally do not think they are ready for prime time. There is significant overhead you need to really make use of them, including possibly installing a managed package authored by UnofficialSF.
In short, as of Summer 21 (api v52), please avoid CPE unless you are willing to accept the astronomical overhead of implementing CPE. This is a high cost, low reward item unless you are an ISV who wants high fidelity design menus in your Screen Flow LWCs.
The other declarative tool that we often see LWCs being design time configured is at the App Builder layer via the design properties. Building on the first section, @api decorator
, once you get the ergonomics sorted out you can extend them into the App Builder by exposing your suite of @api
decorated props to the App Builder.