UNPKG

@polymer/polymer

Version:

The Polymer library makes it easy to create your own web components. Give your element some markup and properties, and then use it on a site. Polymer provides features like dynamic templates and data binding to reduce the amount of boilerplate you need to

152 lines (142 loc) 6.18 kB
<!-- @license Copyright (c) 2017 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 --> <link rel="import" href="../utils/templatize.html"> <script> (function() { 'use strict'; let TemplateInstanceBase = Polymer.TemplateInstanceBase; // eslint-disable-line /** * @typedef {{ * _templatizerTemplate: HTMLTemplateElement, * _parentModel: boolean, * _instanceProps: Object, * _forwardHostPropV2: Function, * _notifyInstancePropV2: Function, * ctor: TemplateInstanceBase * }} */ let TemplatizerUser; // eslint-disable-line /** * The `Polymer.Templatizer` behavior adds methods to generate instances of * templates that are each managed by an anonymous `Polymer.PropertyEffects` * instance where data-bindings in the stamped template content are bound to * accessors on itself. * * This behavior is provided in Polymer 2.x as a hybrid-element convenience * only. For non-hybrid usage, the `Polymer.Templatize` library * should be used instead. * * Example: * * // Get a template from somewhere, e.g. light DOM * let template = this.querySelector('template'); * // Prepare the template * this.templatize(template); * // Instance the template with an initial data model * let instance = this.stamp({myProp: 'initial'}); * // Insert the instance's DOM somewhere, e.g. light DOM * Polymer.dom(this).appendChild(instance.root); * // Changing a property on the instance will propagate to bindings * // in the template * instance.myProp = 'new value'; * * Users of `Templatizer` may need to implement the following abstract * API's to determine how properties and paths from the host should be * forwarded into to instances: * * _forwardHostPropV2: function(prop, value) * * Likewise, users may implement these additional abstract API's to determine * how instance-specific properties that change on the instance should be * forwarded out to the host, if necessary. * * _notifyInstancePropV2: function(inst, prop, value) * * In order to determine which properties are instance-specific and require * custom notification via `_notifyInstanceProp`, define an `_instanceProps` * object containing keys for each instance prop, for example: * * _instanceProps: { * item: true, * index: true * } * * Any properties used in the template that are not defined in _instanceProp * will be forwarded out to the Templatize `owner` automatically. * * Users may also implement the following abstract function to show or * hide any DOM generated using `stamp`: * * _showHideChildren: function(shouldHide) * * Note that some callbacks are suffixed with `V2` in the Polymer 2.x behavior * as the implementations will need to differ from the callbacks required * by the 1.x Templatizer API due to changes in the `TemplateInstance` API * between versions 1.x and 2.x. * * @polymerBehavior */ Polymer.Templatizer = { /** * Generates an anonymous `TemplateInstance` class (stored as `this.ctor`) * for the provided template. This method should be called once per * template to prepare an element for stamping the template, followed * by `stamp` to create new instances of the template. * * @param {!HTMLTemplateElement} template Template to prepare * @param {boolean=} mutableData When `true`, the generated class will skip * strict dirty-checking for objects and arrays (always consider them to * be "dirty"). Defaults to false. * @return {void} * @this {TemplatizerUser} */ templatize(template, mutableData) { this._templatizerTemplate = template; this.ctor = Polymer.Templatize.templatize(template, this, { mutableData: Boolean(mutableData), parentModel: this._parentModel, instanceProps: this._instanceProps, forwardHostProp: this._forwardHostPropV2, notifyInstanceProp: this._notifyInstancePropV2 }); }, /** * Creates an instance of the template prepared by `templatize`. The object * returned is an instance of the anonymous class generated by `templatize` * whose `root` property is a document fragment containing newly cloned * template content, and which has property accessors corresponding to * properties referenced in template bindings. * * @param {Object=} model Object containing initial property values to * populate into the template bindings. * @return {TemplateInstanceBase} Returns the created instance of * the template prepared by `templatize`. * @this {TemplatizerUser} */ stamp(model) { return new this.ctor(model); }, /** * Returns the template "model" (`TemplateInstance`) associated with * a given element, which serves as the binding scope for the template * instance the element is contained in. A template model should be used * to manipulate data associated with this template instance. * * @param {HTMLElement} el Element for which to return a template model. * @return {TemplateInstanceBase} Model representing the binding scope for * the element. * @this {TemplatizerUser} */ modelForElement(el) { return Polymer.Templatize.modelForElement(this._templatizerTemplate, el); } }; })(); </script>