-
Notifications
You must be signed in to change notification settings - Fork 173
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
False arguments serialized as strings #129
Comments
Your example doesn't show your described behaviour. In jsx your example of applying classes wouldn't work that way. <div class={[false, null, undefined, "foo"].filter(Boolean).join(' ')}></div> Which is basicly what clsx is doing. |
Thank you for the answer, but that question is rather design concern, not looking for workaround. That would be natural to visually declare classes instead of array manipulations, I wonder what are the maintainers' opinion on that - if that's worth considering that case. |
Okay, what would you consider the expected behaviour ? htm can 't pass it as an array, because you are not passing an array. Also if it would pass an array the rendering framework (e.g. |
The expected result is the same as when you directly render these values: html`<div>${ false } ${ null } ${ undefined }</div>` It renders blank string here. I'd make rather strong guess that null-ish values are meaningless for all string arguments, ie. if anything is wrapped into a string, it must not be serialized literally: html`<div attr="${false}"/>` // <div attr="" />, not <div attr="false" />
html`<div attr=${false} />` // <div />, not <div attr="false" /> Mb that's a bit too smart though, but practically useful. |
That is behaviour of preact not Also as I wrote above you can't just remove values as they may be passed to Components using these values and expecting |
The problem is not false/null values, but string attributes - htm does rendering part here, meaningless for classes and possibly all string attributes in general: html`<div attr="foo ${false}"/>`
// expected <div attr="foo" />
// actual <div attr="foo false" /> |
This is not addressable, since the behaviour described would be specific to a given attribute. For example, htm explicitly cannot treat falsy (combined or otherwise) values within some attributes as empty: html`<a aria-hidden="${false}">visible</a>`
// should render <a aria-hidden="false">visible</a>
html`<a aria-hidden=" ${false} ">visible</a>`
// should render <a aria-hidden=" false ">visible</a> While I can see the convenience of special-casing DOMTokenList values in HTM, it's not feasible to implement a scalable solution for doing so. // classnames
const cx = (...a) => a.filter(Boolean).join(' ');
html`<a class=${cx(false, 'hello', null, undefined)}>visible</a>`
// renders <a class="hello">visible</a> In terms of my own preference or recommendation, it seems like this would be nicer to address at the pragma layer. Personally I'd just co-opt function h(tag, props, children) {
if (props && props.classList) props.class = props.classList.filter(Boolean).join(' ');
return { tag, props, children };
}
const html = htm.bind(h);
html`<a classList=${[false, 'hello', null, undefined]}>visible</a>`
// renders <a class="hello">visible</a> |
Just a sidenote, The vscode lit html plugin will warn about this, pretty cool. |
Suppose use-case for conditional applying classes:
Sandbox
That's unexpected that the htm serializes false/null class values literally.
That can be worked around with clsx or alike, but.
The text was updated successfully, but these errors were encountered: