diff --git a/CHANGELOG.md b/CHANGELOG.md index d82269bd..0f57d81b 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -12,6 +12,8 @@ and this project adheres to [Semantic Versioning](http://semver.org/). ## Unreleased +### Changed +* The value returned by `render` is always rendered, even if it isn't a `TemplateResult`. ([#712](https://github.com/Polymer/lit-element/issues/712) ### Added diff --git a/package.json b/package.json index 28f891dc..dc625c66 100644 --- a/package.json +++ b/package.json @@ -63,7 +63,7 @@ }, "typings": "lit-element.d.ts", "dependencies": { - "lit-html": "^1.0.0" + "lit-html": "^1.1.1" }, "publishConfig": { "access": "public" diff --git a/src/lit-element.ts b/src/lit-element.ts index a0b24bd2..765551ea 100644 --- a/src/lit-element.ts +++ b/src/lit-element.ts @@ -11,8 +11,7 @@ * subject to an additional IP rights grant found at * http://polymer.github.io/PATENTS.txt */ -import {TemplateResult} from 'lit-html'; -import {render} from 'lit-html/lib/shady-render.js'; +import {render, ShadyRenderOptions} from 'lit-html/lib/shady-render.js'; import {PropertyValues, UpdatingElement} from './lib/updating-element.js'; @@ -45,15 +44,17 @@ export class LitElement extends UpdatingElement { * optimizations. See updating-element.ts for more information. */ protected static['finalized'] = true; + /** - * Render method used to render the lit-html TemplateResult to the element's - * DOM. - * @param {TemplateResult} Template to render. - * @param {Element|DocumentFragment} Node into which to render. - * @param {String} Element name. + * Render method used to render the value to the element's DOM. + * @param result The value to render. + * @param container Node into which to render. + * @param options Element name. * @nocollapse */ - static render = render; + static render: + (result: unknown, container: Element|DocumentFragment, + options: ShadyRenderOptions) => void = render; /** * Array of styles to apply to the element. The styles should be defined @@ -194,14 +195,11 @@ export class LitElement extends UpdatingElement { */ protected update(changedProperties: PropertyValues) { super.update(changedProperties); - const templateResult = this.render() as unknown; - if (templateResult instanceof TemplateResult) { - (this.constructor as typeof LitElement) - .render( - templateResult, - this.renderRoot, - {scopeName: this.localName, eventContext: this}); - } + (this.constructor as typeof LitElement) + .render( + this.render(), + this.renderRoot, + {scopeName: this.localName, eventContext: this}); // When native Shadow DOM is used but adoptedStyles are not supported, // insert styling after rendering to ensure adoptedStyles have highest // priority. @@ -216,10 +214,12 @@ export class LitElement extends UpdatingElement { } /** - * Invoked on each update to perform rendering tasks. This method must return - * a lit-html TemplateResult. Setting properties inside this method will *not* - * trigger the element to update. + * Invoked on each update to perform rendering tasks. This method may return + * any value renderable by lit-html's NodePart - typically a TemplateResult. + * Setting properties inside this method will *not* trigger the element to + * update. */ - protected render(): TemplateResult|void { + protected render(): unknown { + return undefined; } } diff --git a/src/test/lit-element_styling_test.ts b/src/test/lit-element_styling_test.ts index 731c44d2..fb7eaa9e 100644 --- a/src/test/lit-element_styling_test.ts +++ b/src/test/lit-element_styling_test.ts @@ -798,6 +798,62 @@ suite('Static get styles', () => { const bodyStyles = `${cssModule}`; assert.equal(bodyStyles, '.my-module { color: yellow; }'); }); + + test( + 'Styles are not removed if the first rendered value is undefined.', + async () => { + const localName = generateElementName(); + + class SomeCustomElement extends LitElement { + static styles = css`:host {border: 4px solid black;}`; + + renderUndefined: boolean; + + constructor() { + super(); + this.renderUndefined = true; + } + + static get properties() { + return { + renderUndefined: { + type: Boolean, + value: true, + }, + }; + } + + render() { + if (this.renderUndefined) { + return undefined; + } + + return htmlWithStyles`Some text.`; + } + } + customElements.define(localName, SomeCustomElement); + + const element = document.createElement(localName) as SomeCustomElement; + document.body.appendChild(element); + + await (element as LitElement).updateComplete; + assert.equal( + getComputedStyle(element) + .getPropertyValue('border-top-width') + .trim(), + '4px'); + + element.renderUndefined = false; + + await (element as LitElement).updateComplete; + assert.equal( + getComputedStyle(element) + .getPropertyValue('border-top-width') + .trim(), + '4px'); + + document.body.removeChild(element); + }); }); suite('ShadyDOM', () => {