Status: IMPLEMENTED
Champion: Mohammed Abdul Sattar (abdulsattar)
Revision: latest
RFC created: 2021/07/05
Last updated: 2022/09/21
RFC: https://github.com/salesforce/lwc-rfcs/pull/52
This RFC has been merged
# Spreading Properties to Child Elements
# Summary
This proposal adds a mechanism to pass a dynamic properties to elements in
an LWC template using a new directive lwc:spread
.
# Example
// x/myComponent.js
export default class MyComponent extends LightningElement {
childProps = {
name: "My Child",
};
}
// x/myComponent.html
<template>
<x-child lwc:spread={childProps}></x-child>
</template>
The new lwc:spread
directive applies childProps
as properties to x-child
.
# Motivation
In LWC, there is no way to pass props to a child component when the component author doesn't know in advance all the props that are needed.
One such usecase is lwc:dynamic
which allows component authors to lazily instantiate components. However,
the props that we pass to the component can't be dynamic: we need to pass them in the template HTML itself.
This is a problem when the component constructor is changed at runtime: the new constructor might need a different set of properties than the earlier one.
We can, of course, not pass any props and once the element renders, query the
element and set the props programmatically. We lose reactivity this way and also force
the component to handle null
props which might not be desirable.
This proposal allows not just lwc:dynamic
but all other elements to accept an object which is bound as props
at runtime.
# Prior Art
- React (JSX Spread Operator)
- Vue (
v-bind
) - Svelte (Spread Props)
- Lit (Discussion for support, PR)
# Detailed Design
A new LWC directive, lwc:spread
will be introduced that can be used to spread the props to children elements.
# Structure
It accepts an object with keys as the property names and values. This object is merged with props passed in the template (essentially Object.assign
). There is no special handling/transformation
of props whatsoever.
For example, event handlers like onclick
aren't specially handled as addEventListener
like LWC does if it sees an onclick
in the template. They'll be assigned just like any other poperty. Also, LWC binds the component to the event handlers defined in the template. lwc:spread
won't do any of that.
# Overriding props
<template>
<c-child name="Hello" lwc:spread={childProps}></c-child>
</template>
childProps = { name: "World" };
lwc:spread
will always be applied last. That means it will take precedence to whatever props are declared in the
template directly. In the above example, c-child
is always passed World
as name
. Additionally, there can be only one lwc:spread
on a directive.
# Locker Integration
Since lwc:spread
allows setting any property, there is a risk of component authors trying to assign properties like innerHTML
.
To prevent this, usage of lwc:spread
will mark the element as risky and add the renderer
key to the element
in the template so that locker can sanitize those properties.
# Drawbacks
One of the biggest drawbacks is that it prevents static analysis of the component. However, if components were using the programmatic way of assigning properties, then those were not statically analyzable anyway.
# Adoption strategy
This feature will be behind a perm. It'll be allowed to customers on a case-by-case basis and when the team is fully confident of the design, it'll be open to all.