Skip to content

Svelte 5: Programmatically creating snippets #9980

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

Closed
andersekdahl opened this issue Dec 21, 2023 · 4 comments
Closed

Svelte 5: Programmatically creating snippets #9980

andersekdahl opened this issue Dec 21, 2023 · 4 comments

Comments

@andersekdahl
Copy link

Describe the problem

I've had the need to create snippets (specifically for the children prop) both in unit tests as well as in Storybook. My current workaround has been to create a new component which passes what I need as children to the component I want to test. But that creates indirection since I need to place that in a separate file.

Describe the proposed solution

It would be great to have some built-in API to define a snippet function without having to have a .svelte file. This would simplify testing components with @testing-library/svelte as well as passing args as snippet props in Storybook.

Alternatives considered

As mentioned I've been defining new components in new files that pass the snippets I want, but I don't think that's a good long-term solution.

Importance

nice to have

@DarioArena87
Copy link

I've found the same issues using StoryBook and in developing a custom cell renderer for an AgGrid.
Often when using a grid not only to display data but also to modify it (even in a simple crud application) it is nice to create a renderer to have a special cell in each row with some controls (maybe a button for the edit that opens a modal with a form to edit the element and one for the deletion that deletes the row).
In the AgGrid case some frameworks like React, Angular and Vue has first class support and defining a cell renderer is often a one-liner (example: AgGrid React). If you look at the example provided for the "totalValueRenderer" it is very little code compared to the "vanilla js" version that requires to implement a class and manually creating the html string and adding it to the DOM (with the relative event listeners): JavaScript AgGrid.
To use the latter in a svelte application i somewhat managed to make things work by using Svelte's client side component api to render a single component defined in a separate .svelte file. I'm still learning svelte so i'm not an expert and to make things a little bit more manageable i followed this StackOverflow's answer as an inspiration and i've defined my renderer like this (code has been simplified):

const columnDefs = [
    ...
    {
      maxWidth: 50,
      cellRenderer: cellRendererFactory((c, p) => {
        const deleteButton = new Button({
          target: c.eGui,
          props: {
            icon: 'fa-solid:trash',
            class: 'px-0 mx-0',
            small: true
          }
        });
   
        deleteButton.$on('click', event => {
          removeRow(p.node.rowIndex);
        });
       
        return deleteButton;
      }),
    }

But i think that this is a lot of work in respect to something, for example, like this:

function deleteButton({c, p}) {
    return <Button small icon='fa-solid:trash' class='px-0 mx-0' on:click={event => removeRow(p.node.rowIndex)}/>
}

const columnDefs = [
    ...
    {
      maxWidth: 50,
      cellRenderer: deleteButton
    }

Furthermore, if the rendered component should be a "composite" (eg. a span or a div with two buttons as children) i have not found anything simple to use searching in svelte docs or by googling it, so i resorted to the intermediary .svelte file.

@alanxp
Copy link

alanxp commented Feb 17, 2024

Support this 100%, i would LOVE to have snippets just like in react micro components.

Without the need for an extra file for the micro component

@wobsoriano
Copy link

Svelte 5 introduced createRawSnippet!

import { createRawSnippet } from 'svelte';

const greet = createRawSnippet((name) => {
	return {
		render: () => `
			<h1>Hello ${name()}!</h1>
		`,
		setup: (node) => {
			$effect(() => {
				node.textContent = `Hello ${name()}!`;
			});
		}
	};
});

@dummdidumm
Copy link
Member

Closed by #12425

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