-
Hello, Recent svelte adopter (and so far mostly enjoyer), I'm trying to find a way to create svelte components from javascript code. Note that I'm using it in SPA mode, so I do not have access to The feature I'm trying to achieve, is on some user action (in this case a large file upload) create a card displaying progress Here a very simple case using pure html: <script lang="ts">
function btnClick(){
let card = document.createElement('div');
let cardcontent = document.createElement('p');
cardcontent.innerText = "Pending Action ...";
card.appendChild(cardcontent);
let cardbar = document.getElementById("mycards")!;
cardbar.appendChild(card);
}
</script>
<button type"button" onclick={btnClick()}>
click me
</button>
<div id="mycards"></div> In my case I'm using flowbite-svelte, so the idea would be to create a svelte component. Which doesn't work with Browsing the docs, using import { Card } from 'flowbite-svelte';
function btnClick(){
let cardbar = document.getElementById("mycards")!;
let new_card = mount(Card, {target: cardbar});
} It works for the card, but now it's not obvious to me how to set the content, I've tried a few things Idea 1:I thought about using mount all the way down. however it only accepts svelte components as input so elements created with Idea 2:Given my understanding on how svelte works. The content is actually a snippet labelled function btnClick(){
let cardbar = document.getElementById("mycards")!;
const content = `<p>Pending Action ...</p>`
const cardcontent = createRawSnippet(() => {
return {
render: () => content,
setup: (node) => {
$effect(() => {
node.textContent = content;
});
}
}}
);
let new_card = mount(Card, {
target: cardbar,
props: {
class: "action-card",
children: cardcontent,
},
})
} Which appears to be correct for my JS linters, but does not display the content inside the card. I'm not sure this Idea 3 (aka 0'):That card is just a Best, |
Beta Was this translation helpful? Give feedback.
Replies: 1 comment 4 replies
-
It depends on what the content is and where it is supposed to come from. You can e.g. reference snippets defined in the markup and snippets that don't use local state can also be exported from the module script. That may be easier than working with One can also import components and pass those as props & add them in the receiving component's markup. Regarding the approach using Though if you create a wrapper, you could also add an element inside the card and expose that; this way you can add DOM elements directly to the component. <!-- CardWrapper.svelte -->
<script>
import Card from './Card.svelte';
const { ...rest } = $props();
let contents;
export { contents }
</script>
<Card {...rest}>
<div bind:this={contents}></div>
</Card> <script>
import { mount } from 'svelte';
import CardWrapper from './CardWrapper.svelte';
let cards;
async function btnClick() {
const content = document.createElement('p');
content.textContent = 'Pending Action...';
const card = await mount(CardWrapper, {
target: cards,
props: { class: "action-card" },
});
card.contents.append(content);
}
</script>
<button onclick={btnClick}>Add</button>
<div bind:this={cards} ></div> |
Beta Was this translation helpful? Give feedback.
It depends on what the content is and where it is supposed to come from. You can e.g. reference snippets defined in the markup and snippets that don't use local state can also be exported from the module script. That may be easier than working with
createRawSnippet
which is not really meant for general use.One can also import components and pass those as props & add them in the receiving component's markup.
Regarding the approach using
createRawSnippet
, that works if theCard
actually renderschildren
.If that is not the case, the library may still be using
<slot />
.You could create a wrapper component as a workaround (so you have
<Card {...rest}>{@render children()}</Card>
).Though if …