Skip to content

Reusable HTML snippets (or svelte's answer for React's arrow function components) #3869

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
tompere opened this issue Nov 7, 2019 · 10 comments

Comments

@tompere
Copy link

tompere commented Nov 7, 2019

Is your feature request related to a problem? Please describe.
Yes! I'm frustrated that we can't reuse simple html code within a single component file, to use internally by this component alone (i.e. "arrow function components" in React)...

consider the following component:

<script>
let id, src, ... // more props
</script>

{#if id === 'x'}
	<h1>I am X</h1>
	<div>
	  <img src={src} .../>
	</div>
{:else if id === 'y'}
	<h2>I am Y</h2>
	<div>
	  <img src={src} .../>
	</div>
{:else if id === 'z'}
	<h3>I am Z</h3>
	<div>
	  <img src={src} .../>
	</div>
{:else}
	<pre>not supported</pre>
{/if}

Since the <div><img .../></div> snippet is reused, my code is now bloated with boilerplate 😞 .

Describe the solution you'd like

<script>
let id, src, ... // more props
</script>

<script type="scopedComponent">
const MyImg = `
<div>
  <img src=${src} .../>
</div>
`
</script>

{#if id === 'x'}
	<h1>I am X</h1>
	<MyImg />
{:else if id === 'y'}
	<h2>I am Y</h2>
	<MyImg />
{:else if id === 'z'}
	<h3>I am Z</h3>
	<MyImg />
{:else}
	<pre>not supported</pre>
{/if}
  • the type="scopedComponent" and string template is just a made-up API, don't take it as a suggestion...
  • notice that the scoped component can access the props directly, that is also necessary.

Describe alternatives you've considered
Writing an additional .svelte for the above, But it has its own cost. For example, the reused html requires many props, I need the root component passing them again and again which bloats my code again...

How important is this feature to you?
My team develop a huge-scale and mission critical app based on svelte. Without a simple and elegant solution for reusing code within the same component we're gonna have tons of redundant code.

@tompere tompere changed the title Reusable HTML snippets (i.e. React's arrow function components) Reusable HTML snippets (or svelte's answer for React's arrow function components) Nov 7, 2019
@kevmodrome
Copy link
Contributor

I'm pretty sure you can already do this with a preprocessor. Write one that looks for type="scopedComponent" and replaces all the instances of it in the code.

Personally I don't really see the point of this. I would just make another file and spread the props on each instance. Like so: <MyImg {...props} />

@stephane-vanraes
Copy link
Contributor

As you mention yourself, the best alternative is to make the repeated part it's own component.

I need the root component passing them again and again which bloats my code again...

This can be done with a simple spread operator as <Component {...$$props} />

@rowanparker
Copy link

rowanparker commented Nov 7, 2019

In your example, all the blocks inside your if / else if statements are the same. Only the final else block is different. If that's your actual use case, why not do all that logic in the script block at the top?

@tompere
Copy link
Author

tompere commented Nov 7, 2019

thanks for your comments!

the {...props} we just an example for the complexity cost of splitting a small piece of code into its own component, not the actual problem.

The value here is the same as having private methods in OO languages or arrow functions in React. Both features are popular and useful for reducing code complexity and overhead in many cases, though the language/framework core design pattern is a module (class/component).

@kevmodrome
Copy link
Contributor

If you must have this, write a preprocessor that does this: https://svelte.dev/docs#svelte_preprocess I don't think it's super complicated :)

@david-pershouse
Copy link

I ended up hacking up something when I needed to do this. (not advised)
https://svelte.dev/repl/4531f96e7f8a4d40adfdfd3a4f379893?version=3.12.1

<AsComponent bind:component={template}>
	<div>
	  <img src={src} alt="test image"/>
	</div>
</AsComponent>

then use like

<svelte:component this={template} />

@tompere
Copy link
Author

tompere commented Nov 7, 2019

I ended up hacking up something when I needed to do this. (not advised)
svelte.dev/repl/4531f96e7f8a4d40adfdfd3a4f379893?version=3.12.1

<AsComponent bind:component={template}>
	<div>
	  <img src={src} alt="test image"/>
	</div>
</AsComponent>

then use like

<svelte:component this={template} />

@david-pershouse - looks good at first glance, thanks! I'll check it out!

@david-pershouse
Copy link

It relies on svelte internals so it could break at any time. In my case I didn't have a choice

@Conduitry
Copy link
Member

This has come up before - #2858, #2940, #3562, maybe others - and the decision then had been to use multiple components and/or to use a preprocessor.

@raythurnvoid
Copy link

This feature is going to be implemented with this RFC: sveltejs/rfcs#34

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

7 participants