Closed Nicolab closed 2 years ago
Hi @Nicolab,
As of right now, <slot />
is not supported. If you could explain how you would like these to work, and what you're trying to solve I can look into supporting them.
Thanks!
Hi @jhukdev,
Thanks for your reply.
I use the custom element (Preactement) to render on the server side the raw HTML, then take over with the front. Example (ideally):
<x-article articleId="1">
<h3 class="title"><slot name="title">Article title</slot></h3>
<p class="content"><slot name="content">Article content</slot></p>
</x-article>
<x-article articleId="2">
<h3 class="title"><slot name="title">Article title 2</slot></h3>
<p class="content"><slot name="content">Article content 2</slot></p>
</x-article>
This could also have the form of
<h3 class="title" slot="title">Article title 2</h3>
, why not, it's shorter.
The article title and/or content can be edited in Article
component (<x-article>
tag). With a onClick
, a form is displayed and after the submit, <slot name="title">{state.title}</slot>
and/or <slot name="content">{state.content}</slot>
should be rendered instead of the original content rendered by the server.
There are plenty of practical uses that would bring another dimension to deal between static content returned by the server and dynamic content generated by the front end (including REST requests, user interactions, ...).
preact-custom-element
could do this but it renders 2 times the content of slots and props.children
. This makes it impractical to handle static server-generated content via front-end dynamism.
There are some closed issues on preact-custom-element
about this, but it is advised to go through the shadow DOM, which I want to avoid to not mess me with the CSS (especially with CSS frameworks that have no effect on the shadow DOM). It seems that this behavior will not be changed in preact-custom-element
.
preactement
works as desired, if there is slot support it would be perfect :rocket:
* I hope I am clear, my English is not great
Hi @Nicolab,
Thanks for taking the time to outline what you're looking for.
This sounds totally doable, I've noticed the code in preact-custom-element
that handles <slot />
's, so based on your description above, I should be able to get a PR together from this.
When I get some time, I'll make a start on this. I'll ping you here with an update 👍
Hi @Nicolab,
Just so I'm clear, I see that preact-custom-element
is assigning the value of the element with a slot
attribute to the components props, e.g:
/**
* Example HTML custom element
*/
<x-article>
<span slot="testSlot">Hello</span>
</x-article>
/*[...]*/
/**
* Example component defined as <x-article />
*/
function Article({ testSlot }) {
console.log(testSlot); // <-- Will equal element value, e.g "<slot name="testSlot">Hello</slot>"
return (
<div>
{testSlot}
</div>
);
}
Is this correct?
Excellent, thank you!
Will equal element value, e.g "
<slot name="testSlot">Hello</slot>
" .... Is this correct?
Yes, I'm pretty sure that this is the same behavior.
https://github.com/preactjs/preact-custom-element/blob/master/src/index.test.jsx#L170
This requires a little trick if we want to get the content only (Hello
here) but it looks fine!
@Nicolab Hey!
By popular demand, a working PR with slot support: https://github.com/jhukdev/preactement/pull/5
This works in a few ways (to my preference, tell me if I'm wrong!). I've allowed the slot value to be either a string primitive if that's the only content type (saves having to parse VDom), or a VDom tree if there's some more complex HTML structure within.
I've outlined a couple of examples below.
Primitive String
/**
* Example HTML custom element
*/
<x-article>
<span slot="testSlot">Hello</span>
</x-article>
/**
* Example component defined as <x-article />
*/
function Article({ testSlot }) {
console.log(testSlot); // <-- Will equal string primitive "Hello"
return (
<div>
{testSlot}
</div>
);
}
VDom Tree
/**
* Example HTML custom element
*/
<x-article>
<span slot="testSlot">
<em class="text">Well, Hello!</em>
</span>
</x-article>
/**
* Example component defined as <x-article />
*/
function Article({ testSlot }) {
console.log(testSlot); // <-- Will equal VDom "<em class="text">Well, Hello!</em>"
return (
<div>
{testSlot}
</div>
);
}
Let me know what you think, and whether this is something that would work. It's also worth noting that the <* slot="{key}" />
elements are removed from this.props.children
to avoid duplicate content, or having to mitigate that.
Very nice. Yes, I prefer this way because it's more clean and flexible. We are able to get only the content Hello
without element, it's handy. We can also get all elements if we want.
It's perfect, thanks! :+1:
@Nicolab Ok, merged and published: https://github.com/jahilldev/preactement/releases/tag/1.6.0
I've put together a demo here: https://github.com/jahilldev/preactement-htmlslots
Let me know how you get on 👍
@Nicolab I'm going to mark this as done, let me know if you have any issues.
Thanks for the suggestion!
Hey, sorry I didn't see your messages. I have seen the demo, this is perfect, thank you very much! Really :+1: I will integrate in my projects after the holidays :smiley:
Have a good end of year!
Hello,
preactement supports the slots?
Example:
In the HTML (DOM):
In the component JSX:
Both are displayed.