Skip to content

Commit

Permalink
feat: add _createPropertyObserver() to PolylitMixin (#8144)
Browse files Browse the repository at this point in the history
  • Loading branch information
web-padawan authored Nov 14, 2024
1 parent f31d9af commit 6a1c452
Show file tree
Hide file tree
Showing 2 changed files with 87 additions and 3 deletions.
25 changes: 22 additions & 3 deletions packages/component-base/src/polylit-mixin.js
Original file line number Diff line number Diff line change
Expand Up @@ -217,12 +217,16 @@ const PolylitMixinImplementation = (superclass) => {
this.__runObservers(props, this.constructor.__observers);
}

if (this.__dynamicPropertyObservers) {
this.__runDynamicObservers(props, this.__dynamicPropertyObservers);
}

if (this.constructor.__complexObservers) {
this.__runComplexObservers(props, this.constructor.__complexObservers);
}

if (this.__dynamicObservers) {
this.__runComplexObservers(props, this.__dynamicObservers);
if (this.__dynamicMethodObservers) {
this.__runComplexObservers(props, this.__dynamicMethodObservers);
}

if (this.constructor.__notifyProps) {
Expand Down Expand Up @@ -257,11 +261,17 @@ const PolylitMixinImplementation = (superclass) => {

/** @protected */
_createMethodObserver(observer) {
const dynamicObservers = getOrCreateMap(this, '__dynamicObservers');
const dynamicObservers = getOrCreateMap(this, '__dynamicMethodObservers');
const { method, observerProps } = parseObserver(observer);
dynamicObservers.set(method, observerProps);
}

/** @protected */
_createPropertyObserver(property, method) {
const dynamicObservers = getOrCreateMap(this, '__dynamicPropertyObservers');
dynamicObservers.set(method, property);
}

/** @private */
__runComplexObservers(props, observers) {
observers.forEach((observerProps, method) => {
Expand All @@ -275,6 +285,15 @@ const PolylitMixinImplementation = (superclass) => {
});
}

/** @private */
__runDynamicObservers(props, observers) {
observers.forEach((prop, method) => {
if (props.has(prop) && this[method]) {
this[method](this[prop], props.get(prop));
}
});
}

/** @private */
__runObservers(props, observers) {
props.forEach((v, k) => {
Expand Down
65 changes: 65 additions & 0 deletions packages/component-base/test/polylit-mixin.test.js
Original file line number Diff line number Diff line change
Expand Up @@ -634,6 +634,71 @@ describe('PolylitMixin', () => {
});
});

describe('dynamic property observer', () => {
let element;
let valueChangedSpy;

const tag = defineCE(
class extends PolylitMixin(LitElement) {
static get properties() {
return {
value: {
type: String,
},
};
}

render() {
return html`${this.value}`;
}

_valueChanged(_value, _oldValue) {}

_valueChangedOther(_value, _oldValue) {}
},
);

beforeEach(async () => {
element = fixtureSync(`<${tag}></${tag}>`);
valueChangedSpy = sinon.spy(element, '_valueChanged');
await element.updateComplete;
});

it('should run dynamic property observer once a property value changes', async () => {
element.value = 'foo';
await element.updateComplete;
expect(valueChangedSpy.calledOnce).to.be.false;

element._createPropertyObserver('value', '_valueChanged');
element.value = 'bar';
await element.updateComplete;
expect(valueChangedSpy.calledOnce).to.be.true;
});

it('should pass old and new value to dynamic property observer', async () => {
element.value = 'foo';
await element.updateComplete;

element._createPropertyObserver('value', '_valueChanged');

element.value = 'bar';
await element.updateComplete;
expect(valueChangedSpy.getCall(0).args).to.deep.equal(['bar', 'foo']);
});

it('should support creating multiple dynamic property observers', async () => {
element._createPropertyObserver('value', '_valueChanged');

const otherObserverSpy = sinon.spy(element, '_valueChangedOther');
element._createPropertyObserver('value', '_valueChangedOther');

element.value = 'bar';
await element.updateComplete;
expect(valueChangedSpy.calledOnce).to.be.true;
expect(otherObserverSpy.calledOnce).to.be.true;
});
});

describe('dynamic method observer', () => {
let element;
let valueOrLoadingChangedSpy;
Expand Down

0 comments on commit 6a1c452

Please sign in to comment.