Skip to content

Proposal: Reusable template blocks #2858

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
RedHatter opened this issue May 24, 2019 · 4 comments
Closed

Proposal: Reusable template blocks #2858

RedHatter opened this issue May 24, 2019 · 4 comments

Comments

@RedHatter
Copy link
Contributor

I often find my self writing code like the following.

<span on:click={doThing}>The same content</span>
{#if something}
  <div>wrapping element <span on:click={doThing}>The same content</span></div>
{/if}

{#each things as thing}
  <div>{thing} <span on:click={doThing}>The same content</span></div>
{/each>

For the the purposes of DRY I would normally extract the repeating span to another component but do so can complicate styling and state access. In addition only one component would use the new component.

I propose a way of writing reusable inline blocks. Something like this.

{#block span}
  <span on:click={doThing}>The same content</span>
{/block}

{#use span}
{#if something}
  <div>wrapping element {#use span}</div>
{/if}

{#each things as thing}
  <div>{thing} {#use span}</div>
{/each>
@RedHatter RedHatter changed the title Proposal: inline components Proposal: Reusable template blocks May 24, 2019
@trbrc
Copy link
Contributor

trbrc commented May 27, 2019

Something like this would be very useful. I wonder if it can be done without introducing new #use syntax, and instead use it like a regular component, ie something like:

{#block Span}
  <span on:click={doThing}>The same content</span>
{/block}

<Span />

{#if something}
  <div>wrapping element <Span /></div>
{/if}

{#each things as thing}
  <div>{thing} <Span /></div>
{/each>

It could simply work like an imported .svelte file, but share the script and style with the rest of the component. That way you’re more free to refactor your components without having to introduce new files. It could support slots too, though I’m not sure how props might work.

@Conduitry
Copy link
Member

I can't find the issue right now, but something like this for defining inline mini-components was considered and rejected in the past. This does seem more doable if it's more or less treated as a macro with no special scoping, but at that point this could also be implemented with preprocessors.

@MVSICA-FICTA
Copy link

There is also this useful proposal: #2940

@RedHatter
Copy link
Contributor Author

In case anyone is interested here's a preprocessor to implement this.

    svelte({
      preprocess: {
        markup: input => {
          const blocks = {}
          const code = input.content
            .replace(/<!--block\s+(.+?)\s*-->([^]+?)<!--end-->/g, (_, name, block) => (blocks[name] = block, ''))
            .replace(/<!--use\s+(.+?)\s*?-->/g, (_, name) => blocks[name])
          return { code }
        }
    })

Example

<!--block span-->
  <span on:click={doThing}>The same content</span>
<!--end-->

<!--use span-->
{#if something}
  <div>wrapping element <!--use span--></div>
{/if}

{#each things as thing}
  <div>{thing} <!--use span--></div>
{/each>

I used comments so tools such as prettier still work.

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

4 participants