Description
When passing data to a custom element, there are two possibilities — properties, or attributes.
Right now, Svelte doesn't have any understanding of custom elements, so on encountering something like this...
<custom-element foo='bar'></custom-element>
...it will look here, fail to find a property corresponding to the foo
attribute, and fall back to writing this:
setAttribute(custom_element, "foo", "bar");
That's sub-optimal, because it means we can't pass down non-string values — especially not objects and arrays. For those, we need to use props.
At the same time, always using props could be a problem for custom elements that expect attributes to change. It's also a problem if a custom element has CSS like this, say...
:host([active]) {
font-weight: bold;
}
...because then if you have a situation like this...
<custom-element active='{{thing === selected}}'></custom-element>
...the prop will be maintained correctly but the attribute won't ever change, meaning the styles will never apply.
A possible solution
Do both. Or rather, always set a prop, but also set an attribute if the value is primitive.
So the example at the top would become this:
custom_element.foo = "bar";
setAttribute(custom_element, "foo", "bar");
For dynamic values, it would be more like this:
custom_element.foo = state.bar;
if (typeof state.bar === "boolean" || typeof state.bar === "undefined") {
if (state.bar) {
setAttribute(custom_element, "foo", "");
} else {
removeAttribute(custom_element, "foo");
}
} elseif (typeof state.bar === "string" || typeof state.bar === "number") {
setAttribute(custom_element, "foo", state.bar);
}
Needless to say, all that logic would live in a helper.
kebab-case vs camelCase
Since props can't be kebab-case, I propose that we translate kebab to camel when setting props:
<custom-element the-answer='{{fortyTwo}}'></custom-element>
custom_element.theAnswer = state.fortyTwo;
setCustomElementAttribute(custom_element, "the-answer", state.fortyTwo);
This might seem slightly messy, but I think it's the most pragmatic way to deal with this stuff, and the way that will result in the least surprising behaviour for the largest number of people. No-one ever said custom elements were particularly well designed. (Actually, lots of people did, but most of them work for Google.)
Thoughts?