Skip to content
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

different attribute handling in div/span etc. and svg #240

Open
rozek opened this issue Feb 16, 2023 · 6 comments
Open

different attribute handling in div/span etc. and svg #240

rozek opened this issue Feb 16, 2023 · 6 comments

Comments

@rozek
Copy link

rozek commented Feb 16, 2023

I am using "htm" with "preact" binding

When I'm using code like the following

render(html`
  <div  id=${false && 'id-1'} />
  <span id=${false && 'id-2'} />
  <svg  id=${false && 'id-3'}></svg>
  <svg  id=${true  && 'id-4'}></svg>
`, document.body)

"htm" handles the ids differently:

  • <div/> and <span/> get an id with the value "false" while
  • <svg/> elements behave as expected (the first one gets no id, the second one an id with the value id-4)

Is that the expected behaviour? I've also tested other attributes, always with the same result...

@rozek
Copy link
Author

rozek commented Feb 16, 2023

Strange...

the behaviour described above seems to depend on the kind of attribute: code like

render(html`
  <div id=${false && 'id'} class=${false && 'class'}
    style=${false && 'style'} custom=${false && 'custom'}></div>
`, document.body)

produces <div id="false"></div>.

Right now, it seems that the id attribute is treated in a special way...

As a consequence, I'll use the following code as a workaround from now on:

render(html`
  <div id=${props.id != null ? id : undefined}
    other=${(props.other != null) && props.other} ...
  ></div>
`, document.body)

@developit
Copy link
Owner

This is how Preact works - it is setting the id property, not the id attribute. When you assign a non-string value to a DOM reflected property like id, it will generally be cast to a string.

This is why youre seeing different behavior for style. The style property setter accepts a string, which it applies as style.cssText. This behavior is not available on SVGElements however, because many HTMLElement properties are not implemented by SVGElement and Preact will instead fall back to assigning your prop as an attribute.

@rozek
Copy link
Author

rozek commented Feb 17, 2023

Oh, good to know...

Thank you very much for this explanation!

@kylebakerio
Copy link

kylebakerio commented Nov 28, 2023

I'm not sure I understand this. But I think it may be related an issue I'm having...

If I want to dynamically set an <img src="${dynamicUri}"/>, I seem to get a random hanging "div" string in the parent somewhere, weird artifacts. It just feels like I can't use dynamic string content without breaking things. I find this really unpredictable behavior and it's turning me off of htm, which I otherwise find pretty exciting (I hate the idea of needing the compilation step with JSX and am trying to avoid that dependency).

What's going on here?

likewise,

<div class="miniboard-thumb" style="background-image: ${baseLayerThumb};"/>

produces

but if I use static style props (e.g. style="height: 100px"), it works as expected...

edit:

Ok, this seems to work:

            let baseLayerThumb = generateStageThumbnail(konvaStage);
            // console.log('baselayer', baseLayerThumb);
            let attr = {style:`background-image: url(${baseLayerThumb});`};

            return html`
                <div class="miniboard">
                    <div class="miniboard-thumb" ...${attr}>

this seems like a pretty basic, critical use case, and it's weird that it doesn't 'just work'. Is this really the way to do it, it can't be inline?

@rschristian
Copy link

produces

Looks like you forgot to wrap the output in a backtick, so GitHub tried to render it directly.

<div class="miniboard-thumb" style="background-image: ${baseLayerThumb};"/>

This works just fine, albeit once you add content to the div (else there would be nothing to apply that background-image to)

this seems like a pretty basic, critical use case, and it's weird that it doesn't 'just work'.

Can you provide a more full example? Do you have some build tooling stepping in here and causing issues? This does "just work".

@cben
Copy link

cben commented Jul 3, 2024

It shouldn't matter whether you extract an object ...${attr} or place it inline.
I suspect the difference is that you forgot url() around it:

-style="background-image: ${baseLayerThumb};
+style="background-image: url(${baseLayerThumb});

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

5 participants