From 7150f4cbabda9603bd5540d5b3ad434ce0ba6c28 Mon Sep 17 00:00:00 2001 From: nd0ut Date: Tue, 10 Oct 2023 13:55:04 +0300 Subject: [PATCH] fix: require `ctx-name` attribute for all the public blocks and wait for it with 300ms timeout this is required mostly for Angular projects, because it sets binded attributes async --- abstract/Block.js | 19 ++++++++++++++++++- abstract/SolutionBlock.js | 1 + blocks/Config/Config.js | 2 ++ blocks/DataOutput/DataOutput.js | 1 + blocks/ShadowWrapper/ShadowWrapper.js | 15 +++++++++------ blocks/UploadCtxProvider/UploadCtxProvider.js | 4 +++- solutions/file-uploader/inline/demo.htm | 4 ++-- solutions/file-uploader/minimal/demo.htm | 1 + solutions/file-uploader/regular/demo.htm | 4 ++-- 9 files changed, 39 insertions(+), 12 deletions(-) diff --git a/abstract/Block.js b/abstract/Block.js index c475ffaa3..ffa9b1c3f 100644 --- a/abstract/Block.js +++ b/abstract/Block.js @@ -8,6 +8,7 @@ import { sharedConfigKey } from './sharedConfigKey.js'; import { toKebabCase } from '../utils/toKebabCase.js'; import { warnOnce } from '../utils/warnOnce.js'; import { getPluralForm } from '../utils/getPluralForm.js'; +import { waitForAttribute } from '../utils/waitForAttribute.js'; const TAG_PREFIX = 'lr-'; @@ -16,6 +17,7 @@ export class Block extends BaseComponent { /** @type {string | null} */ static StateConsumerScope = null; static className = ''; + requireCtxName = false; allowCustomTemplate = true; init$ = blockCtx(); @@ -137,7 +139,22 @@ export class Block extends BaseComponent { this.constructor['template'] = null; this.processInnerHtml = true; } - super.connectedCallback(); + if (this.requireCtxName) { + waitForAttribute({ + element: this, + attribute: 'ctx-name', + onMutate: () => { + // async wait for ctx-name attribute to be set, needed for Angular because it sets attributes after mount + // TODO: should be moved to the symbiote core + super.connectedCallback(); + }, + onTimeout: () => { + console.error('Attribute `ctx-name` is required and it is not set.'); + }, + }); + } else { + super.connectedCallback(); + } } disconnectedCallback() { diff --git a/abstract/SolutionBlock.js b/abstract/SolutionBlock.js index 9dc23104d..6a4160940 100644 --- a/abstract/SolutionBlock.js +++ b/abstract/SolutionBlock.js @@ -2,6 +2,7 @@ import { ShadowWrapper } from '../blocks/ShadowWrapper/ShadowWrapper.js'; import { uploaderBlockCtx } from './CTX.js'; export class SolutionBlock extends ShadowWrapper { + requireCtxName = true; init$ = uploaderBlockCtx(this); _template = null; diff --git a/blocks/Config/Config.js b/blocks/Config/Config.js index 0368efbf9..fa169455f 100644 --- a/blocks/Config/Config.js +++ b/blocks/Config/Config.js @@ -4,6 +4,7 @@ import { initialConfig } from './initialConfig.js'; import { sharedConfigKey } from '../../abstract/sharedConfigKey.js'; import { toKebabCase } from '../../utils/toKebabCase.js'; import { normalizeConfigValue } from './normalizeConfigValue.js'; +import { waitForAttribute } from '../../utils/waitForAttribute.js'; const allConfigKeys = /** @type {(keyof import('../../types').ConfigType)[]} */ (Object.keys(initialConfig)); @@ -40,6 +41,7 @@ const attrStateMapping = /** @type {Record { - let href = this.getAttribute(CSS_ATTRIBUTE); - if (href) { + waitForAttribute({ + element: this, + attribute: CSS_ATTRIBUTE, + onMutate: (href) => { this.attachShadow({ mode: 'open', }); @@ -53,11 +55,12 @@ export function shadowed(Base) { }; // @ts-ignore TODO: fix this this.shadowRoot.prepend(link); - } else { + }, + onTimeout: () => { console.error( 'Attribute `css-src` is required and it is not set. See migration guide: https://uploadcare.com/docs/file-uploader/migration-to-0.25.0/' ); - } + }, }); } }; diff --git a/blocks/UploadCtxProvider/UploadCtxProvider.js b/blocks/UploadCtxProvider/UploadCtxProvider.js index 9b978809c..70b169dda 100644 --- a/blocks/UploadCtxProvider/UploadCtxProvider.js +++ b/blocks/UploadCtxProvider/UploadCtxProvider.js @@ -1,3 +1,5 @@ import { UploaderBlock } from '../../abstract/UploaderBlock.js'; -export class UploadCtxProvider extends UploaderBlock {} +export class UploadCtxProvider extends UploaderBlock { + requireCtxName = true; +} diff --git a/solutions/file-uploader/inline/demo.htm b/solutions/file-uploader/inline/demo.htm index d2672b8f9..dd824b284 100644 --- a/solutions/file-uploader/inline/demo.htm +++ b/solutions/file-uploader/inline/demo.htm @@ -27,7 +27,7 @@

Multiple sources

- +

Single source

@@ -60,5 +60,5 @@

Single source

- + diff --git a/solutions/file-uploader/minimal/demo.htm b/solutions/file-uploader/minimal/demo.htm index cc64fce46..d28290f17 100644 --- a/solutions/file-uploader/minimal/demo.htm +++ b/solutions/file-uploader/minimal/demo.htm @@ -18,6 +18,7 @@

Live example

Button with modal window - +

Single source

@@ -37,6 +37,6 @@

Single source

- +