Skip to content

Commit

Permalink
fix(modal): rerender when action slot is added
Browse files Browse the repository at this point in the history
- the slot decorator doesnt update when the slot changes, so a slot listener must be added
- a slot lister cannot be added to a slot that doesnt exist
- instead, always render the slot, but use the hidden attribute
- the slot change event will force the component to update and get the new value of the slot property

fixes vmware-clarity#188
  • Loading branch information
Ashley Ryan committed Nov 2, 2022
1 parent 17b5842 commit 9e4c267
Show file tree
Hide file tree
Showing 2 changed files with 39 additions and 12 deletions.
35 changes: 35 additions & 0 deletions projects/core/src/modal/modal.element.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@ describe('modal element', () => {
let testElement: HTMLElement;
let component: CdsModal;
let scrollComponent: CdsModal;
let noActionsComponent: CdsModal;
const placeholderHeader = 'I have a nice title';
const placeholderContent = 'But not much to say...';
const placeholderActionText = 'Ok';
Expand All @@ -43,14 +44,23 @@ describe('modal element', () => {
>
<cds-modal-actions>${placeholderAction}</cds-modal-actions>
</cds-modal>
<cds-modal id="no-actions-modal" style="--max-height: 400px" hidden>
<cds-modal-header>${placeholderHeader}</cds-modal-header>
<cds-modal-content
><div style="padding-bottom: 1200px"><p>${placeholderContent}</p></div></cds-modal-content
>
</cds-modal>
`);
component = testElement.querySelector<CdsModal>('#normal-modal');
scrollComponent = testElement.querySelector<CdsModal>('#scroll-modal');
noActionsComponent = testElement.querySelector<CdsModal>('#no-actions-modal');
});

afterEach(() => {
removeTestElement(testElement);
removeTestElement(scrollComponent);
removeTestElement(noActionsComponent);
});

it('should create the component', async () => {
Expand Down Expand Up @@ -244,4 +254,29 @@ describe('modal element', () => {
component.shadowRoot.querySelector<CdsInternalCloseButton>('cds-internal-close-button').click();
expect((await event).detail).toBe('close-button-click');
});

it('should rerender when action slot is added', async () => {
await componentIsStable(noActionsComponent);

let slots = getComponentSlotContent(noActionsComponent);

const slot = noActionsComponent.shadowRoot.querySelector('slot[name="modal-actions"]');

expect(slots['modal-actions']).not.toContain(`${placeholderActionText}`);
expect(slot.parentElement.hasAttribute('hidden')).toBe(true);

await new Promise(resolve =>
setTimeout(() => {
noActionsComponent.innerHTML =
noActionsComponent.innerHTML +
`<cds-modal-actions><cds-button>${placeholderActionText}</cds-button></cds-modal-actions>`;
resolve('ok');
}, 100)
);

await componentIsStable(noActionsComponent);
slots = getComponentSlotContent(noActionsComponent);
expect(slots['modal-actions']).toContain(`${placeholderActionText}`);
expect(slot.parentElement.hasAttribute('hidden')).toBe(false);
});
});
16 changes: 4 additions & 12 deletions projects/core/src/modal/modal.element.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@
* The full license information can be found in LICENSE in the root directory of this project.
*/

import { html, TemplateResult } from 'lit';
import { html } from 'lit';
import { query } from 'lit/decorators/query.js';
import {
animate,
Expand Down Expand Up @@ -92,16 +92,6 @@ export class CdsModal extends CdsInternalOverlay {

protected isScrollable = false;

private get modalFooterTemplate(): TemplateResult {
if (this.modalFooter) {
return html`<div cds-layout="align-stretch p-x:lg">
<slot name="modal-actions"></slot>
</div>`;
} else {
return html``;
}
}

protected observers: (MutationObserver | ResizeObserver)[] = [];

// modal-body requires a tab index so it can be scrolled
Expand All @@ -123,7 +113,9 @@ export class CdsModal extends CdsInternalOverlay {
<div class="modal-body" cds-layout="p-x:lg">
<slot></slot>
</div>
${this.modalFooterTemplate}
<div cds-layout="align-stretch p-x:lg" ?hidden=${!this.modalFooter}>
<slot name="modal-actions" @slotchange=${() => this.requestUpdate()}></slot>
</div>
</div>
<div cds-layout="display:screen-reader-only">${this.i18n.contentEnd}</div>
</div>
Expand Down

0 comments on commit 9e4c267

Please sign in to comment.