Skip to content

Commit

Permalink
feat: add setProperties() method to PolylitMixin (#7041)
Browse files Browse the repository at this point in the history
  • Loading branch information
web-padawan authored Dec 29, 2023
1 parent 713f714 commit 8faedfa
Show file tree
Hide file tree
Showing 2 changed files with 75 additions and 0 deletions.
23 changes: 23 additions & 0 deletions packages/component-base/src/polylit-mixin.js
Original file line number Diff line number Diff line change
Expand Up @@ -93,6 +93,9 @@ const PolylitMixinImplementation = (superclass) => {

let result = defaultDescriptor;

// Set the key for this property
this.getOrCreateMap('__propKeys').set(name, key);

if (options.sync) {
result = {
get: defaultDescriptor.get,
Expand Down Expand Up @@ -232,6 +235,26 @@ const PolylitMixinImplementation = (superclass) => {
}
}

/**
* Set several properties at once and perform synchronous update.
* @protected
*/
setProperties(props) {
Object.entries(props).forEach(([name, value]) => {
// Use private key and not setter to not trigger
// update for properties marked as `sync: true`.
const key = this.constructor.__propKeys.get(name);
const oldValue = this[key];
this[key] = value;
this.requestUpdate(name, oldValue);
});

// Perform sync update
if (this.hasUpdated) {
this.performUpdate();
}
}

/** @protected */
_createMethodObserver(observer) {
const dynamicObservers = getOrCreateMap(this, '__dynamicObservers');
Expand Down
52 changes: 52 additions & 0 deletions packages/component-base/test/polylit-mixin.test.js
Original file line number Diff line number Diff line change
Expand Up @@ -1003,4 +1003,56 @@ describe('PolylitMixin', () => {
expect(element.count).to.equal(1);
});
});

describe('setProperties()', () => {
let element;

const tag = defineCE(
class extends PolylitMixin(LitElement) {
static get properties() {
return {
disabled: {
type: Boolean,
sync: true,
},

value: {
type: String,
},
};
}
},
);

beforeEach(async () => {
element = fixtureSync(`<${tag}></${tag}>`);
await element.updateComplete;
});

it('should set property values on the element', () => {
element.setProperties({ value: 'foo', disabled: true });
expect(element.value).to.equal('foo');
expect(element.disabled).to.be.true;
});

it('should request update for each passed property', () => {
const spy = sinon.spy(element, 'requestUpdate');
element.setProperties({ value: 'foo', disabled: true });
expect(spy).to.be.calledTwice;
expect(spy.firstCall.args[0]).to.equal('value');
expect(spy.secondCall.args[0]).to.equal('disabled');
});

it('should only call performUpdate() method once', () => {
const spy = sinon.spy(element, 'performUpdate');
element.setProperties({ value: 'foo', disabled: true });
expect(spy).to.be.calledOnce;
});

it('should not throw when calling before first render', () => {
expect(() => {
document.createElement(tag).setProperties({ disabled: true });
}).to.not.throw(Error);
});
});
});

0 comments on commit 8faedfa

Please sign in to comment.