lit-html
Version:
HTML template literals in JavaScript
77 lines • 3.25 kB
JavaScript
/**
* @license
* Copyright (c) 2018 The Polymer Project Authors. All rights reserved.
* This code may only be used under the BSD style license found at
* http://polymer.github.io/LICENSE.txt
* The complete set of authors may be found at
* http://polymer.github.io/AUTHORS.txt
* The complete set of contributors may be found at
* http://polymer.github.io/CONTRIBUTORS.txt
* Code distributed by Google as part of the polymer project is also
* subject to an additional IP rights grant found at
* http://polymer.github.io/PATENTS.txt
*/
import { directive, NodePart, reparentNodes } from '../lit-html.js';
const partCaches = new WeakMap();
/**
* Efficiently switches between two templates based on the given condition. The
* rendered content is cached, and re-used when switching conditions. Templates
* are evaluated lazily, so the passed values must be functions.
*
* While this directive can render any regular part, it makes the most sense
* when used with TemplateResult since most other values are dirty checked
* already.
*
* Example:
*
* let checked = false;
*
* html`
* when(checked, () => html`Checkmark is checked`, () => html`Checkmark is not
* checked`);
* `
*
* @param condition the condition to test truthiness against
* @param trueValue the value to render given a true condition
* @param falseValue the value to render given a false condition
*/
export const when = (condition, trueValue, falseValue) => directive((parentPart) => {
let cache = partCaches.get(parentPart);
// Create a new cache if this is the first render
if (cache === undefined) {
// Cache consists of two parts, one for each condition, and a
// docment fragment which we cache the nodes of the condition that's
// not currently rendered.
cache = {
truePart: new NodePart(parentPart.templateFactory),
falsePart: new NodePart(parentPart.templateFactory),
cacheContainer: document.createDocumentFragment(),
};
partCaches.set(parentPart, cache);
cache.truePart.appendIntoPart(parentPart);
cache.falsePart.appendIntoPart(parentPart);
}
// Based on the condition, select which part to render and which value
// to set on that part.
const nextPart = condition ? cache.truePart : cache.falsePart;
const nextValue = condition ? trueValue() : falseValue();
// If we switched condition, swap nodes to/from the cache.
if (!!condition !== cache.prevCondition) {
// Get the part which was rendered for the opposite condition. This
// should be added to the cache.
const prevPart = condition ? cache.falsePart : cache.truePart;
// If the next part was rendered, take it from the cache
if (nextPart.value) {
parentPart.startNode.parentNode.appendChild(cache.cacheContainer);
}
// If the prev part was rendered, move it to the cache
if (prevPart.value) {
reparentNodes(cache.cacheContainer, prevPart.startNode, prevPart.endNode.nextSibling);
}
}
// Set the next part's value
nextPart.setValue(nextValue);
nextPart.commit();
cache.prevCondition = !!condition;
});
//# sourceMappingURL=when.js.map