mirror of
https://github.com/sveltejs/svelte.git
synced 2024-11-30 00:46:29 +01:00
[fix] call attribute bindings for custom element if <svelte:element> render custom element (#7766)
* call attr bindings if tag is custom element * add test
This commit is contained in:
parent
c113d9d978
commit
5adac302c0
@ -803,15 +803,31 @@ export default class ElementWrapper extends Wrapper {
|
||||
|
||||
const fn = this.node.namespace === namespaces.svg ? x`@set_svg_attributes` : x`@set_attributes`;
|
||||
|
||||
block.chunks.hydrate.push(
|
||||
b`${fn}(${this.var}, ${data});`
|
||||
);
|
||||
if (this.node.is_dynamic_element) {
|
||||
// call attribute bindings for custom element if tag is custom element
|
||||
const tag = this.node.tag_expr.manipulate(block);
|
||||
const attr_update = b`
|
||||
if (/-/.test(${tag})) {
|
||||
@set_custom_element_data_map(${this.var}, ${data});
|
||||
} else {
|
||||
${fn}(${this.var}, ${data});
|
||||
}`;
|
||||
block.chunks.hydrate.push(attr_update);
|
||||
block.chunks.update.push(b`
|
||||
${data} = @get_spread_update(${levels}, [${updates}]);
|
||||
${attr_update}`
|
||||
);
|
||||
} else {
|
||||
block.chunks.hydrate.push(
|
||||
b`${fn}(${this.var}, ${data});`
|
||||
);
|
||||
|
||||
block.chunks.update.push(b`
|
||||
${fn}(${this.var}, ${data} = @get_spread_update(${levels}, [
|
||||
${updates}
|
||||
]));
|
||||
`);
|
||||
block.chunks.update.push(b`
|
||||
${fn}(${this.var}, ${data} = @get_spread_update(${levels}, [
|
||||
${updates}
|
||||
]));
|
||||
`);
|
||||
}
|
||||
|
||||
// handle edge cases for elements
|
||||
if (this.node.name === 'select') {
|
||||
|
@ -316,6 +316,12 @@ export function set_svg_attributes(node: Element & ElementCSSInlineStyle, attrib
|
||||
}
|
||||
}
|
||||
|
||||
export function set_custom_element_data_map(node, data_map: Record<string, unknown>) {
|
||||
Object.keys(data_map).forEach((key) => {
|
||||
set_custom_element_data(node, key, data_map[key]);
|
||||
});
|
||||
}
|
||||
|
||||
export function set_custom_element_data(node, prop, value) {
|
||||
if (prop in node) {
|
||||
node[prop] = typeof node[prop] === 'boolean' && value === '' ? true : value;
|
||||
|
@ -0,0 +1,47 @@
|
||||
export default {
|
||||
skip_if_ssr: true,
|
||||
props: {
|
||||
tag: 'my-custom-element',
|
||||
name: null
|
||||
},
|
||||
html: `
|
||||
<my-custom-element id="a">Hello null!</my-custom-element>
|
||||
<my-custom-element id="b">Hello null!</my-custom-element>
|
||||
`,
|
||||
|
||||
test({ assert, component, target }) {
|
||||
component.name = undefined;
|
||||
assert.htmlEqual(
|
||||
target.innerHTML,
|
||||
`<my-custom-element id="a">Hello undefined!</my-custom-element>
|
||||
<my-custom-element id="b">Hello undefined!</my-custom-element>`
|
||||
);
|
||||
|
||||
component.name = 'foo';
|
||||
assert.htmlEqual(
|
||||
target.innerHTML,
|
||||
`<my-custom-element id="a">Hello foo!</my-custom-element>
|
||||
<my-custom-element id="b">Hello foo!</my-custom-element>`
|
||||
);
|
||||
|
||||
component.tag = null;
|
||||
assert.htmlEqual(
|
||||
target.innerHTML,
|
||||
'<my-custom-element id="b">Hello foo!</my-custom-element>'
|
||||
);
|
||||
|
||||
component.tag = 'div';
|
||||
assert.htmlEqual(
|
||||
target.innerHTML,
|
||||
`<div name="foo" id="a"></div>
|
||||
<my-custom-element id="b">Hello foo!</my-custom-element>`
|
||||
);
|
||||
|
||||
component.tag = 'my-custom-element';
|
||||
assert.htmlEqual(
|
||||
target.innerHTML,
|
||||
`<my-custom-element id="a">Hello foo!</my-custom-element>
|
||||
<my-custom-element id="b">Hello foo!</my-custom-element>`
|
||||
);
|
||||
}
|
||||
};
|
@ -0,0 +1,32 @@
|
||||
<script>
|
||||
class MyCustomElement extends HTMLElement {
|
||||
constructor() {
|
||||
super();
|
||||
this._name = null;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param {string} name
|
||||
*/
|
||||
set name(name) {
|
||||
this._name = name;
|
||||
this.render();
|
||||
}
|
||||
|
||||
connectedCallback() {
|
||||
this.render();
|
||||
}
|
||||
|
||||
render() {
|
||||
this.innerHTML = "Hello " + this._name + "!";
|
||||
}
|
||||
}
|
||||
|
||||
window.customElements.define("my-custom-element", MyCustomElement);
|
||||
|
||||
export let tag;
|
||||
export let name;
|
||||
</script>
|
||||
|
||||
<svelte:element this="{tag}" {name} id="a" />
|
||||
<my-custom-element {name} id="b" />
|
Loading…
Reference in New Issue
Block a user