Initialize custom elements in connected callback

pull/5139/head
Christopher Mardell 5 years ago
parent d19bcef690
commit 07e2dde83d

@ -90,8 +90,8 @@ export default function dom(
${uses_rest && !uses_props && x`$$props = @assign(@assign({}, $$props), @exclude_internal_props($$new_props))`}
${uses_rest && renderer.invalidate('$$restProps', x`$$restProps = ${compute_rest}`)}
${writable_props.map(prop =>
b`if ('${prop.export_name}' in ${$$props}) ${renderer.invalidate(prop.name, x`${prop.name} = ${$$props}.${prop.export_name}`)};`
)}
b`if ('${prop.export_name}' in ${$$props}) ${renderer.invalidate(prop.name, x`${prop.name} = ${$$props}.${prop.export_name}`)};`
)}
${component.slots.size > 0 &&
b`if ('$$scope' in ${$$props}) ${renderer.invalidate('$$scope', x`$$scope = ${$$props}.$$scope`)};`}
}
@ -190,8 +190,8 @@ export default function dom(
${$$props} => {
${uses_props && renderer.invalidate('$$props', x`$$props = @assign(@assign({}, $$props), $$new_props)`)}
${injectable_vars.map(
v => b`if ('${v.name}' in $$props) ${renderer.invalidate(v.name, x`${v.name} = ${$$props}.${v.name}`)};`
)}
v => b`if ('${v.name}' in $$props) ${renderer.invalidate(v.name, x`${v.name} = ${$$props}.${v.name}`)};`
)}
}
`;
@ -462,10 +462,15 @@ export default function dom(
class ${name} extends @SvelteElement {
constructor(options) {
super();
if (options) {
this.$$runSetup(options);
}
}
$$setup(options) {
console.log("$$setup");
${css.code && b`this.shadowRoot.innerHTML = \`<style>${css.code.replace(/\\/g, '\\\\')}${options.dev ? `\n/*# sourceMappingURL=${css.map.toUrl()} */` : ''}</style>\`;`}
@init(this, { target: this.shadowRoot }, ${definition}, ${has_create_fragment ? 'create_fragment': 'null'}, ${not_equal}, ${prop_indexes}, ${dirty});
@init(this, { props: options ? options.props : null, target: this.shadowRoot }, ${definition}, ${has_create_fragment ? 'create_fragment': 'null'}, ${not_equal}, ${prop_indexes}, ${dirty});
${dev_props_check}

@ -171,7 +171,32 @@ if (typeof HTMLElement === 'function') {
this.attachShadow({ mode: 'open' });
}
$$initialProps: Record<string, any> | null = {};
$$options: Record<string, any> | null = {};
$$setup(_options) {
// overridden by instance
}
$$runSetup(options?: Record<string, any>) {
console.log("$$runSetup");
const {$$initialProps} = this;
if ($$initialProps) {
const opts = (options || this.$$options);
this.$$initialProps = null;
this.$$options = null;
this.$$setup({
...opts,
props: {
...opts.props,
...$$initialProps
}
});
}
}
connectedCallback() {
console.log("connectedCallback");
this.$$runSetup();
// @ts-ignore todo: improve typings
for (const key in this.$$.slotted) {
// @ts-ignore todo: improve typings
@ -179,7 +204,12 @@ if (typeof HTMLElement === 'function') {
}
}
// initial implementation of method, will be overridden on setup
attributeChangedCallback(attr, _oldValue, newValue) {
console.log(`attributeChangedCallback: ${attr}, ${newValue}`);
if (this.$$initialProps) {
this.$$initialProps[attr] = newValue;
}
this[attr] = newValue;
}
@ -199,7 +229,12 @@ if (typeof HTMLElement === 'function') {
};
}
$set() {
$set(obj) {
if (this.$$initialProps && obj) {
for (const attr of Object.getOwnPropertyNames(obj)) {
this.$$initialProps[attr] = obj[attr];
}
}
// overridden by instance, if it has props
}
};

@ -0,0 +1,8 @@
<svelte:options tag="custom-element"/>
<script>
export let items = [];
</script>
<p>{items.length} items</p>
<p>{items.join(', ')}</p>

@ -0,0 +1,23 @@
import * as assert from 'assert';
import CustomElement from './main.svelte';
export default async function (target) {
const el = new CustomElement();
assert.equal(el.outerHTML, '<custom-element></custom-element>');
// const el = target.querySelector('custom-element');
assert.equal(el.shadowRoot, undefined);
el.items = ['a', 'b', 'c'];
const [p1, p2] = el.shadowRoot.querySelectorAll('p');
assert.equal(p1.textContent, '3 items');
assert.equal(p2.textContent, 'a, b, c');
el.items = ['d', 'e', 'f', 'g', 'h'];
assert.equal(p1.textContent, '5 items');
assert.equal(p2.textContent, 'd, e, f, g, h');
}

@ -1,7 +1,7 @@
import * as assert from 'assert';
import CustomElement from './main.svelte';
export default function (target) {
export default async function (target) {
new CustomElement({
target
});
@ -9,8 +9,15 @@ export default function (target) {
assert.equal(target.innerHTML, '<custom-element></custom-element>');
const el = target.querySelector('custom-element');
// await new Promise((resolve) => setTimeout(resolve, 100));
// await new Promise((resolve) => setTimeout(resolve, 100));
const widget = el.shadowRoot.querySelector('my-widget');
console.log(widget);
// await new Promise((resolve) => setTimeout(resolve, 100));
const [p1, p2] = widget.shadowRoot.querySelectorAll('p');
assert.equal(p1.textContent, '3 items');
@ -20,4 +27,4 @@ export default function (target) {
assert.equal(p1.textContent, '5 items');
assert.equal(p2.textContent, 'd, e, f, g, h');
}
}

Loading…
Cancel
Save