Skip to content

Commit cd6dd8a

Browse files
author
Steven Orvell
committed
Ensure attribute reflected from property is correct
Fixes #592. Ensures a reflecting property set immediately after a corresponding attribute reflects correctly.
1 parent fd31a97 commit cd6dd8a

File tree

3 files changed

+41
-6
lines changed

3 files changed

+41
-6
lines changed

CHANGELOG.md

+2
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,8 @@ and this project adheres to [Semantic Versioning](http://semver.org/).
1919
* `LitElement.renderRoot` is now `public readonly` instead of `protected`.
2020

2121
### Fixed
22+
* A reflecting property set immediately after a corresponding attribute
23+
now reflects properly ([#592](https://github.com/Polymer/lit-element/issues/592)).
2224
* Properties annotated with the `@query` and `@queryAll` decorators will now
2325
survive property renaming optimizations when used with tsickle and Closure JS
2426
Compiler.

src/lib/updating-element.ts

+11-6
Original file line numberDiff line numberDiff line change
@@ -579,24 +579,29 @@ export abstract class UpdatingElement extends HTMLElement {
579579
*/
580580
requestUpdate(name?: PropertyKey, oldValue?: unknown) {
581581
let shouldRequestUpdate = true;
582-
// if we have a property key, perform property update steps.
583-
if (name !== undefined && !this._changedProperties.has(name)) {
582+
// If we have a property key, perform property update steps.
583+
if (name !== undefined) {
584584
const ctor = this.constructor as typeof UpdatingElement;
585585
const options =
586586
ctor._classProperties!.get(name) || defaultPropertyDeclaration;
587587
if (ctor._valueHasChanged(
588588
this[name as keyof this], oldValue, options.hasChanged)) {
589-
// track old value when changing.
590-
this._changedProperties.set(name, oldValue);
591-
// add to reflecting properties set
589+
// Track old value when changing.
590+
if (!this._changedProperties.has(name)) {
591+
this._changedProperties.set(name, oldValue);
592+
}
593+
// Add to reflecting properties set.
594+
// Note, it's important that every change has a chance to add the
595+
// property to `_reflectingProperties`. This ensures setting
596+
// attribute + property reflects correctly.
592597
if (options.reflect === true &&
593598
!(this._updateState & STATE_IS_REFLECTING_TO_PROPERTY)) {
594599
if (this._reflectingProperties === undefined) {
595600
this._reflectingProperties = new Map();
596601
}
597602
this._reflectingProperties.set(name, options);
598603
}
599-
// abort the request if the property should not be considered changed.
604+
// Abort the request if the property should not be considered changed.
600605
} else {
601606
shouldRequestUpdate = false;
602607
}

src/test/lib/updating-element_test.ts

+28
Original file line numberDiff line numberDiff line change
@@ -2219,4 +2219,32 @@ suite('UpdatingElement', () => {
22192219
await a.updateComplete;
22202220
assert.equal(a.updatedCalledCount, 1);
22212221
});
2222+
2223+
test('property reflects after setting attribute in same update cycle', async () => {
2224+
class A extends UpdatingElement {
2225+
2226+
foo?: boolean;
2227+
bar?: string;
2228+
2229+
static get properties() {
2230+
return {
2231+
foo: {type: Boolean, reflect: true},
2232+
bar: {type: String, reflect: true}
2233+
};
2234+
}
2235+
2236+
}
2237+
customElements.define(generateElementName(), A);
2238+
const a = new A();
2239+
container.appendChild(a);
2240+
a.setAttribute('foo', '');
2241+
a.removeAttribute('foo');
2242+
a.foo = true;
2243+
await a.updateComplete;
2244+
assert.isTrue(a.hasAttribute('foo'));
2245+
a.setAttribute('bar', 'hi');
2246+
a.bar = 'yo';
2247+
await a.updateComplete;
2248+
assert.equal(a.getAttribute('bar'), 'yo');
2249+
});
22222250
});

0 commit comments

Comments
 (0)