I want to build a custom configurable interface to pass two buttons to header and footer of a standard card element.
So, I have a component card
with card template
<template>
<lightning-card title={title}>
<slot name="cancel" slot="actions"><lightning-button label="Cancel"></lightning-button></slot>
<slot name="save" slot="actions"><lightning-button label="Save"></lightning-button></slot>
Content
<slot name="cancel" slot="footer"><lightning-button label="Cancel"></lightning-button></slot>
<slot name="save" slot="footer"><lightning-button label="Save"></lightning-button></slot>
</lightning-card>
</template>
and another custom component customCard
which uses this template
<template>
<c-card>
<lightning-button label="Cancel" title="Cancel" onclick={handleCancel} class="slds-m-left_x-small"
slot="cancel"></lightning-button>
<lightning-button variant="success" label="Save" title="Save" onclick={handleSave} class="slds-m-left_x-small"
slot="save"></lightning-button>
</c-card>
</template>
When I open card
component, I see both buttons in the header and the footer
When I open customCard
component, I see only buttons in the footer but not in the header
I tried to adopt this approach and define a property with slot list since I cannot set it directly
import { LightningElement } from 'lwc';
export default class Card extends LightningElement {
slots = ['actions','footer'];
}
and then use template:forEach
for LWC
<template for:each={slots} for:item='slot'>
<slot name="cancel" key={slot} slot={slot}><lightning-button label="Cancel"></lightning-button></slot>
</template>
<template for:each={slots} for:item='slot'>
<slot name="save" key={slot} slot={slot}><lightning-button label="Save"></lightning-button></slot>
</template>
however, when I try to deploy this code, it raises an exception
LWC1081: Slot attribute value can't be an expression.
Is there any way to work around this problem?
Update:
I didn't mention that I would like to process the data from properties stored in customCard on save click
So actually I have something like following
<template>
<lightning-card title={title}>
<slot name="cancel" slot="actions"><lightning-button label="Cancel"></lightning-button></slot>
<slot name="save" slot="actions"><lightning-button label="Save"></lightning-button></slot>
<slot>Content</slot>
<slot name="cancel" slot="footer"><lightning-button label="Cancel"></lightning-button></slot>
<slot name="save" slot="footer"><lightning-button label="Save"></lightning-button></slot>
</lightning-card>
</template>
and custom component
<template>
<c-card>
<lightning-button label="Cancel" title="Cancel" onclick={handleCancel} class="slds-m-left_x-small"
slot="cancel"></lightning-button>
<lightning-button variant="success" label="Save" title="Save" onclick={handleSave} class="slds-m-left_x-small"
slot="save"></lightning-button>
<lightning:input value={data1}></lightning:input>
<lightning:input value={data2}></lightning:input>
....
<lightning:input value={data100}></lightning:input>
</c-card>
</template>
and in handleSave
handleSave() {
process(data1);
process(data2);
...
process(data100);
}
Best Answer
So far I ended up with the following code in template component
and the following code in the custom component
however, I personally consider this code ugly and repetitive and I would opt for a better and cleaner solution if such solution exists.