diff --git a/src/Umbraco.Web.UI.Client/src/packages/core/property/property-dataset/property-dataset.element.test.ts b/src/Umbraco.Web.UI.Client/src/packages/core/property/property-dataset/property-dataset.element.test.ts index fd45760328..700bcb0184 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/core/property/property-dataset/property-dataset.element.test.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/core/property/property-dataset/property-dataset.element.test.ts @@ -9,7 +9,7 @@ import { UmbElementMixin } from '@umbraco-cms/backoffice/element-api'; @customElement('test-property-editor') export class UmbTestPropertyEditorElement extends UmbElementMixin(LitElement) { // - #variantContext?: typeof UMB_PROPERTY_DATASET_CONTEXT.TYPE; + _datasetContext?: typeof UMB_PROPERTY_DATASET_CONTEXT.TYPE; @property() public get alias() { @@ -29,17 +29,15 @@ export class UmbTestPropertyEditorElement extends UmbElementMixin(LitElement) { } setValue(value: string) { if (this._alias) { - this.dispatchEvent(new UmbChangeEvent()); - this.#variantContext?.setPropertyValue(this._alias, value); + this._datasetContext?.setPropertyValue(this._alias, value); this.dispatchEvent(new UmbChangeEvent()); } } - private async _observeProperty() { - const alias = this._alias; - if (!this.#variantContext || !alias) return; + protected async _observeProperty() { + if (!this._datasetContext || !this._alias) return; this.observe( - await this.#variantContext.propertyValueByAlias(alias), + await this._datasetContext.propertyValueByAlias(this._alias), (value) => { this._value = value as string; }, @@ -50,12 +48,28 @@ export class UmbTestPropertyEditorElement extends UmbElementMixin(LitElement) { constructor() { super(); this.consumeContext(UMB_PROPERTY_DATASET_CONTEXT, async (variantContext) => { - this.#variantContext = variantContext; + this._datasetContext = variantContext; this._observeProperty(); }); } } +// Adapter property editor, which tests what happens if a editor sets values of other editors. +@customElement('test-adapter-property-editor') +export class UmbTestAdapterPropertyEditorElement extends UmbTestPropertyEditorElement { + protected async _observeProperty() { + super._observeProperty(); + if (!this._datasetContext || !this._alias) return; + this.observe( + await this._datasetContext.propertyValueByAlias(this._alias), + (value) => { + this._datasetContext?.setPropertyValue('testAlias', 'setByAdapter_' + value); + }, + 'observeValue', + ); + } +} + const dataSet: Array = [ { alias: 'testAlias', @@ -64,25 +78,43 @@ const dataSet: Array = [ ]; describe('UmbBasicVariantElement', () => { + describe('Public API', () => { + let datasetElement: UmbPropertyDatasetElement; + + beforeEach(async () => { + datasetElement = await fixture(html` `); + }); + + describe('properties', () => { + it('has a value property', () => { + expect(datasetElement).to.have.property('value').to.be.an.a('array'); + }); + + it('has a name property', () => { + expect(datasetElement).to.have.property('name').to.be.an.a('string'); + }); + }); + }); + describe('Data bindings', () => { - let variantElement: UmbPropertyDatasetElement; + let datasetElement: UmbPropertyDatasetElement; let propertyEditor: UmbTestPropertyEditorElement; beforeEach(async () => { - variantElement = await fixture( + datasetElement = await fixture( html` `, ); - propertyEditor = variantElement.querySelector('test-property-editor') as UmbTestPropertyEditorElement; + propertyEditor = datasetElement.querySelector('test-property-editor') as UmbTestPropertyEditorElement; }); - it('basic-variant is defined with its own instance', () => { - expect(variantElement).to.be.instanceOf(UmbPropertyDatasetElement); + it('is defined with its own instance', () => { + expect(datasetElement).to.be.instanceOf(UmbPropertyDatasetElement); }); - it('property editor gets value', () => { + it('provides the value for the property editor to get', () => { expect(propertyEditor.alias).to.equal('testAlias'); expect(propertyEditor.getValue()).to.equal('testValue'); }); @@ -92,14 +124,14 @@ describe('UmbBasicVariantElement', () => { expect(propertyEditor.getValue()).to.equal('testValue2'); }); - it('property editor sets value on context', () => { + it('retrieves value set by child', () => { propertyEditor.setValue('testValue2'); - expect(variantElement.context.getValues()[0].alias).to.equal('testAlias'); - expect(variantElement.context.getValues()[0].value).to.equal('testValue2'); + expect(datasetElement.context.getValues()[0].alias).to.equal('testAlias'); + expect(datasetElement.context.getValues()[0].value).to.equal('testValue2'); }); - it('variant element fires change event', async () => { - const listener = oneEvent(variantElement, UmbChangeEvent.TYPE); + it('fires change event', async () => { + const listener = oneEvent(datasetElement, UmbChangeEvent.TYPE); expect(propertyEditor.alias).to.eq('testAlias'); propertyEditor.setValue('testValue3'); @@ -107,7 +139,26 @@ describe('UmbBasicVariantElement', () => { const event = (await listener) as unknown as UmbChangeEvent; expect(event).to.exist; expect(event.type).to.eq(UmbChangeEvent.TYPE); - expect(event.target).to.equal(variantElement); + expect(event.target).to.equal(datasetElement); + }); + + it('is does respond to changes triggered internally', async () => { + const adapterPropertyEditor = document.createElement( + 'test-adapter-property-editor', + ) as UmbTestAdapterPropertyEditorElement; + datasetElement.appendChild(adapterPropertyEditor); + + const listener = oneEvent(datasetElement, UmbChangeEvent.TYPE); + + expect(propertyEditor.alias).to.eq('testAlias'); + adapterPropertyEditor.setValue('testValue4'); + + const event = (await listener) as unknown as UmbChangeEvent; + expect(event).to.exist; + expect(event.type).to.eq(UmbChangeEvent.TYPE); + expect(event.target).to.equal(datasetElement); + expect(adapterPropertyEditor.getValue()).to.equal('testValue4'); + expect(propertyEditor.getValue()).to.equal('setByAdapter_testValue4'); }); }); }); diff --git a/src/Umbraco.Web.UI.Client/src/packages/core/property/property-dataset/property-dataset.element.ts b/src/Umbraco.Web.UI.Client/src/packages/core/property/property-dataset/property-dataset.element.ts index 0ab420c2a6..b501549a4c 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/core/property/property-dataset/property-dataset.element.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/core/property/property-dataset/property-dataset.element.ts @@ -11,8 +11,8 @@ import { UmbChangeEvent } from '@umbraco-cms/backoffice/event'; */ @customElement('umb-property-dataset') export class UmbPropertyDatasetElement extends UmbLitElement { - // A take on only firing events when the value is changed from the outside. - #silentOnce = true; + // Determine wether state change should fire an event when the value is changed. + #allowChangeEvent = false; public readonly context: UmbPropertyDatasetBaseContext; @@ -51,9 +51,10 @@ export class UmbPropertyDatasetElement extends UmbLitElement { return this.context.getValues(); } public set value(value: Array) { - this.#silentOnce = true; + this.#allowChangeEvent = false; this.context.setValues(value); - this.#silentOnce = false; + // Above might not trigger a observer callback (if no change), so set the allow change event to true: + this.#allowChangeEvent = true; } /** @@ -74,9 +75,10 @@ export class UmbPropertyDatasetElement extends UmbLitElement { return this.context.getName(); } public set name(value: string | undefined) { - this.#silentOnce = true; + this.#allowChangeEvent = false; this.context.setName(value); - this.#silentOnce = false; + // Above might not trigger a observer callback (if no change), so set the allow change event to true: + this.#allowChangeEvent = true; } constructor() { @@ -90,23 +92,23 @@ export class UmbPropertyDatasetElement extends UmbLitElement { }); this.context = new UmbPropertyDatasetBaseContext(this); - this.observe(this.context.name, () => { - if (!this.#silentOnce) { - this.dispatchEvent(new UmbChangeEvent()); - } else { - this.#silentOnce = false; - } - }); - this.#silentOnce = true; - this.observe(this.context.values, () => { - if (!this.#silentOnce) { - this.dispatchEvent(new UmbChangeEvent()); - } else { - this.#silentOnce = false; - } - }); + // prevent the first change event from firing: + this.#allowChangeEvent = false; + this.observe(this.context.name, this.#observerCallback); + // prevent the first change event from firing: + this.#allowChangeEvent = false; + this.observe(this.context.values, this.#observerCallback); } + #observerCallback = () => { + if (this.#allowChangeEvent) { + this.dispatchEvent(new UmbChangeEvent()); + } else { + // Set allow change event to true. + this.#allowChangeEvent = true; + } + }; + render() { return html``; }