@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
315 lines (283 loc) • 11.8 kB
TypeScript
// tslint:disable:variable-name Describing an API that's defined elsewhere.
// tslint:disable:no-any describes the API as best we are able today
import {PolymerElement} from '../../polymer-element.js';
import {TemplateInstanceBase, templatize, modelForElement} from '../utils/templatize.js';
import {Debouncer} from '../utils/debounce.js';
import {enqueueDebouncer, flush} from '../utils/flush.js';
import {OptionalMutableData} from '../mixins/mutable-data.js';
import {matches, translate} from '../utils/path.js';
import {timeOut, microTask} from '../utils/async.js';
import {hideElementsGlobally} from '../utils/hide-template-controls.js';
export {DomRepeat};
/**
* The `<dom-repeat>` element will automatically stamp and binds one instance
* of template content to each object in a user-provided array.
* `dom-repeat` accepts an `items` property, and one instance of the template
* is stamped for each item into the DOM at the location of the `dom-repeat`
* element. The `item` property will be set on each instance's binding
* scope, thus templates should bind to sub-properties of `item`.
*
* Example:
*
* ```html
* <dom-module id="employee-list">
*
* <template>
*
* <div> Employee list: </div>
* <dom-repeat items="{{employees}}">
* <template>
* <div>First name: <span>{{item.first}}</span></div>
* <div>Last name: <span>{{item.last}}</span></div>
* </template>
* </dom-repeat>
*
* </template>
*
* </dom-module>
* ```
*
* With the following custom element definition:
*
* ```js
* class EmployeeList extends PolymerElement {
* static get is() { return 'employee-list'; }
* static get properties() {
* return {
* employees: {
* value() {
* return [
* {first: 'Bob', last: 'Smith'},
* {first: 'Sally', last: 'Johnson'},
* ...
* ];
* }
* }
* };
* }
* }
* ```
*
* Notifications for changes to items sub-properties will be forwarded to template
* instances, which will update via the normal structured data notification system.
*
* Mutations to the `items` array itself should be made using the Array
* mutation API's on the PropertyEffects mixin (`push`, `pop`, `splice`,
* `shift`, `unshift`), and template instances will be kept in sync with the
* data in the array.
*
* Events caught by event handlers within the `dom-repeat` template will be
* decorated with a `model` property, which represents the binding scope for
* each template instance. The model should be used to manipulate data on the
* instance, for example `event.model.set('item.checked', true);`.
*
* Alternatively, the model for a template instance for an element stamped by
* a `dom-repeat` can be obtained using the `modelForElement` API on the
* `dom-repeat` that stamped it, for example
* `this.$.domRepeat.modelForElement(event.target).set('item.checked', true);`.
* This may be useful for manipulating instance data of event targets obtained
* by event handlers on parents of the `dom-repeat` (event delegation).
*
* A view-specific filter/sort may be applied to each `dom-repeat` by supplying a
* `filter` and/or `sort` property. This may be a string that names a function on
* the host, or a function may be assigned to the property directly. The functions
* should implemented following the standard `Array` filter/sort API.
*
* In order to re-run the filter or sort functions based on changes to sub-fields
* of `items`, the `observe` property may be set as a space-separated list of
* `item` sub-fields that should cause a re-filter/sort when modified. If
* the filter or sort function depends on properties not contained in `items`,
* the user should observe changes to those properties and call `render` to update
* the view based on the dependency change.
*
* For example, for an `dom-repeat` with a filter of the following:
*
* ```js
* isEngineer(item) {
* return item.type == 'engineer' || item.manager.type == 'engineer';
* }
* ```
*
* Then the `observe` property should be configured as follows:
*
* ```html
* <dom-repeat items="{{employees}}" filter="isEngineer" observe="type manager.type">
* ```
*/
declare class DomRepeat extends
OptionalMutableData(
PolymerElement) {
_templateInfo: TemplateInfo|null;
/**
* An array containing items determining how many instances of the template
* to stamp and that that each template instance should bind to.
*/
items: any[]|null|undefined;
/**
* The name of the variable to add to the binding scope for the array
* element associated with a given template instance.
*/
as: string|null|undefined;
/**
* The name of the variable to add to the binding scope with the index
* of the instance in the sorted and filtered list of rendered items.
* Note, for the index in the `this.items` array, use the value of the
* `itemsIndexAs` property.
*/
indexAs: string|null|undefined;
/**
* The name of the variable to add to the binding scope with the index
* of the instance in the `this.items` array. Note, for the index of
* this instance in the sorted and filtered list of rendered items,
* use the value of the `indexAs` property.
*/
itemsIndexAs: string|null|undefined;
/**
* A function that should determine the sort order of the items. This
* property should either be provided as a string, indicating a method
* name on the element's host, or else be an actual function. The
* function should match the sort function passed to `Array.sort`.
* Using a sort function has no effect on the underlying `items` array.
*/
sort: Function|null|undefined;
/**
* A function that can be used to filter items out of the view. This
* property should either be provided as a string, indicating a method
* name on the element's host, or else be an actual function. The
* function should match the sort function passed to `Array.filter`.
* Using a filter function has no effect on the underlying `items` array.
*/
filter: Function|null|undefined;
/**
* When using a `filter` or `sort` function, the `observe` property
* should be set to a space-separated list of the names of item
* sub-fields that should trigger a re-sort or re-filter when changed.
* These should generally be fields of `item` that the sort or filter
* function depends on.
*/
observe: string|null|undefined;
/**
* When using a `filter` or `sort` function, the `delay` property
* determines a debounce time in ms after a change to observed item
* properties that must pass before the filter or sort is re-run.
* This is useful in rate-limiting shuffling of the view when
* item changes may be frequent.
*/
delay: number|null|undefined;
/**
* Count of currently rendered items after `filter` (if any) has been applied.
* If "chunking mode" is enabled, `renderedItemCount` is updated each time a
* set of template instances is rendered.
*/
readonly renderedItemCount: number|null|undefined;
/**
* When greater than zero, defines an initial count of template instances
* to render after setting the `items` array, before the next paint, and
* puts the `dom-repeat` into "chunking mode". The remaining items (and
* any future items as a result of pushing onto the array) will be created
* and rendered incrementally at each animation frame thereof until all
* instances have been rendered.
*/
initialCount: number|null|undefined;
/**
* When `initialCount` is used, this property defines a frame rate (in
* fps) to target by throttling the number of instances rendered each
* frame to not exceed the budget for the target frame rate. The
* framerate is effectively the number of `requestAnimationFrame`s that
* it tries to allow to actually fire in a given second. It does this
* by measuring the time between `rAF`s and continuously adjusting the
* number of items created each `rAF` to maintain the target framerate.
* Setting this to a higher number allows lower latency and higher
* throughput for event handlers and other tasks, but results in a
* longer time for the remaining items to complete rendering.
*/
targetFramerate: number|null|undefined;
readonly _targetFrameTime: number|null|undefined;
/**
* When the global `suppressTemplateNotifications` setting is used, setting
* `notifyDomChange: true` will enable firing `dom-change` events on this
* element.
*/
notifyDomChange: boolean|null|undefined;
/**
* When chunking is enabled via `initialCount` and the `items` array is
* set to a new array, this flag controls whether the previously rendered
* instances are reused or not.
*
* When `true`, any previously rendered template instances are updated in
* place to their new item values synchronously in one shot, and then any
* further items (if any) are chunked out. When `false`, the list is
* returned back to its `initialCount` (any instances over the initial
* count are discarded) and the remainder of the list is chunked back in.
* Set this to `true` to avoid re-creating the list and losing scroll
* position, although note that when changing the list to completely
* different data the render thread will be blocked until all existing
* instances are updated to their new data.
*/
reuseChunkedInstances: boolean|null|undefined;
connectedCallback(): void;
disconnectedCallback(): void;
/**
* Forces the element to render its content. Normally rendering is
* asynchronous to a provoking change. This is done for efficiency so
* that multiple changes trigger only a single render. The render method
* should be called if, for example, template rendering is required to
* validate application state.
*/
render(): void;
/**
* Shows or hides the template instance top level child elements. For
* text nodes, `textContent` is removed while "hidden" and replaced when
* "shown."
*
* @param hidden Set to true to hide the children;
* set to false to show them.
*/
_showHideChildren(hidden: boolean): void;
/**
* Returns the item associated with a given element stamped by
* this `dom-repeat`.
*
* Note, to modify sub-properties of the item,
* `modelForElement(el).set('item.<sub-prop>', value)`
* should be used.
*
* @param el Element for which to return the item.
* @returns Item associated with the element.
*/
itemForElement(el: HTMLElement): any;
/**
* Returns the inst index for a given element stamped by this `dom-repeat`.
* If `sort` is provided, the index will reflect the sorted order (rather
* than the original array order).
*
* @param el Element for which to return the index.
* @returns Row index associated with the element (note this may
* not correspond to the array index if a user `sort` is applied).
*/
indexForElement(el: HTMLElement): number|null;
/**
* Returns the template "model" 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.
*
* Example:
*
* let model = modelForElement(el);
* if (model.index < 10) {
* model.set('item.checked', true);
* }
*
* @param el Element for which to return a template model.
* @returns Model representing the binding scope for
* the element.
*/
modelForElement(el: HTMLElement): TemplateInstanceBase|null;
}
declare global {
interface HTMLElementTagNameMap {
"dom-repeat": DomRepeat;
}
}
import {TemplateInfo} from '../../interfaces';