Skip to content
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

Conditionally add a wrapper/parent tag #7528

Closed
acarl005 opened this issue May 13, 2022 · 2 comments
Closed

Conditionally add a wrapper/parent tag #7528

acarl005 opened this issue May 13, 2022 · 2 comments

Comments

@acarl005
Copy link

acarl005 commented May 13, 2022

Describe the problem

Hello. I have situations where I sometimes want to add a wrapping <div> around some other tag based on a conditional. Currently, I'm doing something like this in my component as a workaround:

{#if needs_div_wrapper}
  <div class="wrapper">
    <p class="lots-of-content">...</p>
  </div>
{:else}
  <p class="lots-of-content">...</p>
{/if}

Notice I had to write <p class="lots-of-content">...</p> twice. That isn't too bad in this example, but in my real scenario I have a HUGE component tree, hence a lot of of duplicated code. I could create another component for that content to minimize the repetition. However, the content is coupled to a lot of props and state in that component, and I don't want to have to pass through a bunch of state, props, and event-handling functions into a new component. It also feels inappropriate to be creating new component files basically just for the purpose of 1 conditional for a tag, which seems like it should be taken care of by the template language.

Describe the proposed solution

Something like this has been proposed before (#3913), though it was stated that the proposal is not acceptable...

{#if needs_div_wrapper}
  <div>
{/if}
    <a>My static content!</a>
{#if needs_div_wrapper}
  </div>
{/if}

Also discussed a bit on stackoverflow.

I will propose other alternatives.

A special svelte attribute?

<div class="wrapper" svelte:if={needs_div_wrapper}>
  <p class="lots-of-content">...</p>
</div>

Something like svelte:if could remove the element/component from the DOM tree and replace it by its children.

As @Conduitry has pointed out...

"Svelte needs to know about the structure of the component at compile time"

So, maybe this solution could just be implemented as mere syntactic sugar for my first example demonstrating the WETness?

Another proposal could be some kind of no-op element.

No-op value to <svelte:element>

<script>
  let wrapper = needs_div_wrapper ? "div" : null
</script>

<svelte:element this={wrapper} class="wrapper">
  <p class="lots-of-content">...</p>
<svelte:element>

<svelte:element> can simply be removed if you pass null (or some other sentinel value) to this.

Or maybe the <svelte:element> could become something like a <svelte:fragment> under a conditional?

Alternatives considered

As of now, I'm just doing what I described above where I need to specify the child element tree twice in the 2 branches of an if block. Would be nice to have 1 of the proposed solutions to DRY things up!

Importance

would make my life easier

@Prinzhorn
Copy link
Contributor

Prinzhorn commented May 13, 2022

You could also use another component + <slot> so you only have

{#if needs_div_wrapper}
  <div class="wrapper">
    <slot />
  </div>
{:else}
   <slot />
{/if}

You can even make that generic by passing the condition + props and use svelte:element for the wrapper. So you can use your ConditionallyWrapped component wherever you need to.

But I think what you really want is inline components sveltejs/rfcs#34

@acarl005
Copy link
Author

@Prinzhorn Ah yes that's a nicer workaround, I'll use that for now until inline components launch. Thanks!!

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

2 participants