Update endpoint params on registered elements

Whenever endpoint-provided value changes, update corresponding attribute
on the plugin provided element. With this change, plugins can receive
updates to the parameters if that's needed.

To take advantage of this change, plugin has few options:

- use a Polymer observers or computed properties
- use `plugin.attributeHelper(element).bind(propertyName, callback)`

Bug: Issue 8162
Change-Id: Ie95f30dd8d840be62cb3370bf39de96672638fd7
This commit is contained in:
Viktar Donich
2018-01-22 14:08:21 -08:00
parent b0f423b0fa
commit 6e1e69bcce
5 changed files with 82 additions and 5 deletions

View File

@@ -150,7 +150,13 @@ The low-level DOM API methods are the base of all UI customization.
=== attributeHelper
`plugin.attributeHelper(element)`
Note: TODO
Alternative for
link:https://www.polymer-project.org/1.0/docs/devguide/data-binding[Polymer data
binding] for plugins that don't use Polymer. Can be used to bind element
attribute changes to callbacks.
See `samples/bind-parameters.html` for examples on both Polymer data bindings
and `attibuteHelper` usage.
=== eventHelper
`plugin.eventHelper(element)`

View File

@@ -83,5 +83,17 @@
return this._promises[name];
};
/**
* Sets value and dispatches event to force notify.
*
* @param {string} name Property name.
* @param {?} value
*/
GrAttributeHelper.prototype.set = function(name, value) {
this.element[name] = value;
this.element.dispatchEvent(
new CustomEvent(this._getChangedEventName(name), {detail: {value}}));
};
window.GrAttributeHelper = GrAttributeHelper;
})(window);

View File

@@ -72,10 +72,14 @@
if (opt_content) {
el.content = opt_content;
}
const expectProperties = this._getEndpointParams().map(
paramEl => plugin.attributeHelper(paramEl).get('value')
.then(value => el[paramEl.getAttribute('name')] = value)
);
const expectProperties = this._getEndpointParams().map(paramEl => {
const helper = plugin.attributeHelper(paramEl);
const paramName = paramEl.getAttribute('name');
return helper.get('value').then(
value => helper.bind('value',
value => plugin.attributeHelper(el).set(paramName, value))
);
});
let timeoutId;
const timeout = new Promise(
resolve => timeoutId = setTimeout(() => {

View File

@@ -148,5 +148,23 @@ limitations under the License.
});
});
});
test('param is bound', done => {
const element =
container.querySelector('gr-endpoint-decorator[name="banana"]');
const param = Polymer.dom(element).querySelector('gr-endpoint-param');
const value1 = {abc: 'def'};
const value2 = {def: 'abc'};
param.value = value1;
plugin.registerCustomComponent('banana', 'noob-noob');
flush(() => {
const module = Polymer.dom(element.root).children.find(
element => element.nodeName === 'NOOB-NOOB');
assert.strictEqual(module['someParam'], value1);
param.value = value2;
assert.strictEqual(module['someParam'], value2);
done();
});
});
});
</script>

View File

@@ -0,0 +1,37 @@
<dom-module id="bind-parameters">
<script>
Gerrit.install(plugin => {
plugin.registerCustomComponent(
'change-view-integration', 'my-bind-sample');
});
</script>
</dom-module>
<dom-module id="my-bind-sample">
<template>
Template example: Patchset number [[revision._number]]. <br/>
Computed example: [[computedExample]].
</template>
<script>
Polymer({
is: 'my-bind-sample',
properties: {
computedExample: {
type: String,
computed: '_computeExample(revision._number)',
},
},
attached() {
this.plugin.attributeHelper(this).bind(
'revision', this._onRevisionChanged.bind(this));
},
_computeExample(value) {
if (!value) { return '(empty)'; }
return `(patchset ${value} selected)`;
},
_onRevisionChanged(value) {
console.log(`(attributeHelper.bind) revision number: ${value._number}`);
},
});
</script>
</dom-module>