Skip to content

Commit

Permalink
make sure that requestContentUpdate is called only once when multiple…
Browse files Browse the repository at this point in the history
… renderers
  • Loading branch information
vursen committed Apr 29, 2022
1 parent 1700867 commit 7496188
Show file tree
Hide file tree
Showing 2 changed files with 28 additions and 21 deletions.
8 changes: 7 additions & 1 deletion packages/dialog/src/vaadin-dialog-lit-renderers.js
Original file line number Diff line number Diff line change
Expand Up @@ -4,8 +4,12 @@
* This program is available under Apache License Version 2.0, available at https://vaadin.com/license/
*/
import { directive } from 'lit/directive.js';
import { microTask } from '@vaadin/component-base/src/async.js';
import { Debouncer } from '@vaadin/component-base/src/debounce.js';
import { LitRendererDirective } from '@vaadin/lit-renderer';

const RUN_RENDERER_DEBOUNCER = Symbol('runRendererDebouncer');

export class DialogRendererDirective extends LitRendererDirective {
/**
* A property to that the renderer callback will be assigned.
Expand All @@ -27,7 +31,9 @@ export class DialogRendererDirective extends LitRendererDirective {
* Runs the renderer callback on the dialog.
*/
runRenderer() {
this.element.requestContentUpdate();
this.element[RUN_RENDERER_DEBOUNCER] = Debouncer.debounce(this.element[RUN_RENDERER_DEBOUNCER], microTask, () => {
this.element.requestContentUpdate();
});
}

/**
Expand Down
41 changes: 21 additions & 20 deletions packages/dialog/test/lit-renderers.test.js
Original file line number Diff line number Diff line change
@@ -1,11 +1,11 @@
import { expect } from '@esm-bundle/chai';
import { fixtureSync, oneEvent } from '@vaadin/testing-helpers';
import { fixtureSync, nextFrame, oneEvent } from '@vaadin/testing-helpers';
import sinon from 'sinon';
import '../vaadin-dialog.js';
import { html, render } from 'lit';
import { dialogFooterRenderer, dialogHeaderRenderer, dialogRenderer } from '../vaadin-dialog.js';

function renderDialog(container, { header, content, footer }) {
async function renderDialog(container, { header, content, footer }) {
render(
html`<vaadin-dialog
${content ? dialogRenderer(() => html`${content}`, content) : null}
Expand All @@ -14,6 +14,7 @@ function renderDialog(container, { header, content, footer }) {
></vaadin-dialog>`,
container,
);
await nextFrame();
}

describe('lit renderers', () => {
Expand All @@ -25,7 +26,7 @@ describe('lit renderers', () => {

describe('dialogRenderer', () => {
beforeEach(async () => {
renderDialog(container, { content: 'Content' });
await renderDialog(container, { content: 'Content' });
dialog = container.querySelector('vaadin-dialog');
overlay = dialog.$.overlay;
dialog.opened = true;
Expand All @@ -36,20 +37,20 @@ describe('lit renderers', () => {
expect(overlay.textContent).to.equal('Content');
});

it('should re-render the dialog content when a renderer dependency changes', () => {
renderDialog(container, { content: 'New Content' });
it('should re-render the dialog content when a renderer dependency changes', async () => {
await renderDialog(container, { content: 'New Content' });
expect(overlay.textContent).to.equal('New Content');
});

it('should clear the dialog content when the directive is detached', () => {
renderDialog(container, {});
it('should clear the dialog content when the directive is detached', async () => {
await renderDialog(container, {});
expect(overlay.textContent).to.be.empty;
});
});

describe('dialogHeaderRenderer', () => {
beforeEach(async () => {
renderDialog(container, { header: 'Header' });
await renderDialog(container, { header: 'Header' });
dialog = container.querySelector('vaadin-dialog');
overlay = dialog.$.overlay;
dialog.opened = true;
Expand All @@ -61,20 +62,20 @@ describe('lit renderers', () => {
expect(header.textContent).to.equal('Header');
});

it('should re-render the dialog header when a renderer dependency changes', () => {
renderDialog(container, { header: 'New Header' });
it('should re-render the dialog header when a renderer dependency changes', async () => {
await renderDialog(container, { header: 'New Header' });
expect(header.textContent).to.equal('New Header');
});

it('should clear the dialog header when the directive is detached', () => {
renderDialog(container, {});
it('should clear the dialog header when the directive is detached', async () => {
await renderDialog(container, {});
expect(overlay.querySelector('[slot=header-content]')).to.be.null;
});
});

describe('dialogFooterRenderer', () => {
beforeEach(async () => {
renderDialog(container, { footer: 'Footer' });
await renderDialog(container, { footer: 'Footer' });
dialog = container.querySelector('vaadin-dialog');
overlay = dialog.$.overlay;
dialog.opened = true;
Expand All @@ -86,20 +87,20 @@ describe('lit renderers', () => {
expect(footer.textContent).to.equal('Footer');
});

it('should re-render the dialog footer when a renderer dependency changes', () => {
renderDialog(container, { footer: 'New Footer' });
it('should re-render the dialog footer when a renderer dependency changes', async () => {
await renderDialog(container, { footer: 'New Footer' });
expect(footer.textContent).to.equal('New Footer');
});

it('should clear the dialog footer when the directive is detached', () => {
renderDialog(container, {});
it('should clear the dialog footer when the directive is detached', async () => {
await renderDialog(container, {});
expect(overlay.querySelector('[slot=footer]')).to.be.null;
});
});

describe('multiple renderers', () => {
beforeEach(async () => {
renderDialog(container, {
await renderDialog(container, {
header: 'Header',
footer: 'Footer',
content: 'Content',
Expand All @@ -109,9 +110,9 @@ describe('lit renderers', () => {
await oneEvent(dialog.$.overlay, 'vaadin-overlay-open');
});

it('should request a content update only once when triggering directives to update', () => {
it('should request a content update only once when triggering directives to update', async () => {
const spy = sinon.spy(dialog, 'requestContentUpdate');
renderDialog(container, {
await renderDialog(container, {
header: 'New Header',
footer: 'New Footer',
content: 'New Content',
Expand Down

0 comments on commit 7496188

Please sign in to comment.