Skip to content

Commit

Permalink
Merge pull request #5035 from Polymer/4458-kschaaf-basic-templatizer
Browse files Browse the repository at this point in the history
Allow templatizer to be used without owner or host prop forwarding. Fixes #4458
  • Loading branch information
Steve Orvell authored Jan 29, 2018
2 parents db95d42 + ecb1005 commit a73fdd7
Show file tree
Hide file tree
Showing 3 changed files with 87 additions and 13 deletions.
43 changes: 31 additions & 12 deletions lib/utils/templatize.html
Original file line number Diff line number Diff line change
Expand Up @@ -77,7 +77,8 @@
children.push(n);
n.__templatizeInstance = this;
}
if (this.__templatizeOwner.__hideTemplateChildren__) {
if (this.__templatizeOwner &&
this.__templatizeOwner.__hideTemplateChildren__) {
this._showHideChildren(true);
}
// Flush props only when props are passed if instance props exist
Expand All @@ -96,15 +97,15 @@
*/
_configureProperties(props) {
let options = this.__templatizeOptions;
if (props) {
for (let iprop in options.instanceProps) {
if (iprop in props) {
this._setPendingProperty(iprop, props[iprop]);
}
if (options.forwardHostProp) {
for (let hprop in this.__hostProps) {
this._setPendingProperty(hprop, this.__dataHost['_host_' + hprop]);
}
}
for (let hprop in this.__hostProps) {
this._setPendingProperty(hprop, this.__dataHost['_host_' + hprop]);
// Any instance props passed in the constructor will overwrite host props;
// normally this would be a user error but we don't specifically filter them
for (let iprop in props) {
this._setPendingProperty(iprop, props[iprop]);
}
}
/**
Expand Down Expand Up @@ -226,6 +227,15 @@
}
return model;
}

/**
* Stub of HTMLElement's `dispatchEvent`, so that effects that may
* dispatch events safely no-op.
*
* @param {Event} event Event to dispatch
*/
dispatchEvent(event) { // eslint-disable-line no-unused-vars
}
}

/** @type {!DataTemplate} */
Expand Down Expand Up @@ -383,12 +393,11 @@
* // Customize property forwarding and event model decoration
* let TemplateClass = Polymer.Templatize.templatize(template, this, {
* parentModel: true,
* instanceProps: {...},
* forwardHostProp(property, value) {...},
* instanceProps: {...},
* notifyInstanceProp(instance, property, value) {...},
* });
*
*
* @namespace
* @memberof Polymer
* @summary Module for preparing and stamping instances of templates
Expand Down Expand Up @@ -440,6 +449,15 @@
* from `instance.parentModel` in cases where template instance nesting
* causes an inner model to shadow an outer model.
*
* When `options.forwardHostProp` is declared as an option, any properties
* referenced in the template will be automatically forwarded from the host of
* the `<template>` to instances, with the exception of any properties listed in
* the `options.instanceProps` object. `instanceProps` are assumed to be
* managed by the owner of the instances, either passed into the constructor
* or set after the fact. Note, any properties passed into the constructor will
* always be set to the instance (regardless of whether they would normally
* be forwarded from the host).
*
* Note that the class returned from `templatize` is generated only once
* for a given `<template>` using `options` from the first call for that
* template, and the cached class is returned for all subsequent calls to
Expand All @@ -451,7 +469,7 @@
*
* @memberof Polymer.Templatize
* @param {!HTMLTemplateElement} template Template to templatize
* @param {!Polymer_PropertyEffects} owner Owner of the template instances;
* @param {Polymer_PropertyEffects=} owner Owner of the template instances;
* any optional callbacks will be bound to this owner.
* @param {Object=} options Options dictionary (see summary for details)
* @return {function(new:TemplateInstanceBase)} Generated class bound to the template
Expand All @@ -464,7 +482,8 @@
throw new Error('A <template> can only be templatized once');
}
template.__templatizeOwner = owner;
let templateInfo = owner.constructor._parseTemplate(template);
const ctor = owner ? owner.constructor : TemplateInstanceBase;
let templateInfo = ctor._parseTemplate(template);
// Get memoized base class for the prototypical template, which
// includes property effects for binding template & forwarding
let baseClass = templateInfo.templatizeInstanceClass;
Expand Down
38 changes: 38 additions & 0 deletions test/unit/templatize.html
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,8 @@
</head>
<body>

<template id="standalone"><div prop="[[prop]]">[[text]]</div></template>

<script>

suite('templatize basic', function() {
Expand Down Expand Up @@ -328,6 +330,42 @@

});

suite('templatize with no host', function() {

test('stamped with initial data', function() {
const template = document.getElementById('standalone').cloneNode(true);
const Template = Polymer.Templatize.templatize(template);
const inst = new Template({prop: 'prop', text: 'text'});
const div = inst.root.firstChild;
assert.equal(div.prop, 'prop');
assert.equal(div.textContent, 'text');
});

test('stamped with no initial data', function() {
const template = document.getElementById('standalone').cloneNode(true);
const Template = Polymer.Templatize.templatize(template);
const inst = new Template();
const div = inst.root.firstChild;
assert.equal(div.prop, undefined);
assert.equal(div.textContent.trim(), '');
inst.setProperties({prop: 'prop', text: 'text'});
assert.equal(div.prop, 'prop');
assert.equal(div.textContent, 'text');
});

test('notifies path data changes', function() {
const template = document.getElementById('standalone').cloneNode(true);
const Template = Polymer.Templatize.templatize(template);
const inst = new Template();
const div = inst.root.firstChild;
inst.setProperties({prop: {foo: true}});
assert.equal(div.prop.foo, true);
inst.set('prop.foo', false);
assert.equal(div.prop.foo, false);
});

});

</script>
</body>
</html>
19 changes: 18 additions & 1 deletion types/lib/utils/templatize.d.ts
Original file line number Diff line number Diff line change
Expand Up @@ -65,6 +65,14 @@ declare class TemplateInstanceBase extends
* set to false to show them.
*/
_showHideChildren(hide: boolean): void;

/**
* Stub of HTMLElement's `dispatchEvent`, so that effects that may
* dispatch events safely no-op.
*
* @param event Event to dispatch
*/
dispatchEvent(event: Event|null): any;
}

declare namespace templateInfo {
Expand Down Expand Up @@ -121,6 +129,15 @@ declare namespace Polymer {
* from `instance.parentModel` in cases where template instance nesting
* causes an inner model to shadow an outer model.
*
* When `options.forwardHostProp` is declared as an option, any properties
* referenced in the template will be automatically forwarded from the host of
* the `<template>` to instances, with the exception of any properties listed in
* the `options.instanceProps` object. `instanceProps` are assumed to be
* managed by the owner of the instances, either passed into the constructor
* or set after the fact. Note, any properties passed into the constructor will
* always be set to the instance (regardless of whether they would normally
* be forwarded from the host).
*
* Note that the class returned from `templatize` is generated only once
* for a given `<template>` using `options` from the first call for that
* template, and the cached class is returned for all subsequent calls to
Expand All @@ -133,7 +150,7 @@ declare namespace Polymer {
* @returns Generated class bound to the template
* provided
*/
function templatize(template: HTMLTemplateElement, owner: Polymer.PropertyEffects, options?: object|null): {new(): TemplateInstanceBase};
function templatize(template: HTMLTemplateElement, owner?: Polymer.PropertyEffects|null, options?: object|null): {new(): TemplateInstanceBase};


/**
Expand Down

0 comments on commit a73fdd7

Please sign in to comment.