Vue: Can not clear slot content with [email protected]

Created on 15 Nov 2017  ·  19Comments  ·  Source: vuejs/vue

Version

2.5.3

Reproduction link

https://jsfiddle.net/yibuyisheng/s5xoxmv1/6/

Steps to reproduce

Create a Base Component with a slot, and pass in the slot with template tag with empty content.

What is expected?

The empty template slot should clear the content of Base Component's corresponding slot.

What is actually happening?

Did not clear the content.


However, the [email protected] do the right thing: https://jsfiddle.net/yibuyisheng/s5xoxmv1/7/

Most helpful comment

IMO 2.4.4 is behaving incorrectly and 2.5.3 fixes the behavior. By design, fallback content appears when a slot receives nothing or all whitespace. "Clearing a slot's fallback content with an empty <template> slot" sounds like a hack to me.

However if you still want to do that, you can use the zero-width space (&#8203;) as slot content.

All 19 comments

IMO 2.4.4 is behaving incorrectly and 2.5.3 fixes the behavior. By design, fallback content appears when a slot receives nothing or all whitespace. "Clearing a slot's fallback content with an empty <template> slot" sounds like a hack to me.

However if you still want to do that, you can use the zero-width space (&#8203;) as slot content.

Using zero-width space to express “clearing the fallback content of a slot” sounds like a hack to me either...is there a better way for us to solve this with more explicit semantics?

You can always add a prop "useDefaultSlot"(defaults to true) and use it
like

default content

On Thu, Nov 16, 2017, 11:58 GU Yiling notifications@github.com wrote:

Using zero-width space to express “clearing the fallback content of a
slot” sounds like a hack to me either...is there a better way for us to
solve this with more explicit semantics?


You are receiving this because you are subscribed to this thread.
Reply to this email directly, view it on GitHub
https://github.com/vuejs/vue/issues/7064#issuecomment-344808843, or mute
the thread
https://github.com/notifications/unsubscribe-auth/AFTLl7p9MpfDOiLP2UdCn5UuRih6ZgZOks5s27LTgaJpZM4QewVf
.

@fnlctrl

Consider you have a complex component with multiple slots, you wouldn't want to expose that kind of prop to each of them. Using slots means we prefer a declarative way to define content, otherwise we can just ignore the slot syntax and pass render functions through props.

@fnlctrl
Maybe we should add useDefaultSlot to the template attribute, and provide a global config to indicate the default override behavior.

@Justineo For complex component with multiple slots, even if we provided an official api to suppress default content, users would still have to declare which slots to be suppressed.
e.g.

<foo :defaults="{slotA: false, slotB: false}"/>

And I don't think it's any better than declaring props in userland.

The best way I can think of is to simply use an empty <div> or <p> or whatever tag like

<foo>
  <p slot="a"/>
  <p slot="b"/>
</foo>

It's simple and declarative.

Actually I'm not seeing why the behavior back to 2.4.4 is undesired. By declaring <template slot="a">...</template>, users are already explicitly overriding the fallback content, otherwise they wouldn't declare them at all. If they want to conditionally override the fallback content, they can apply v-if like <template slot="a" v-if="override">.

And I don't think it's any better than declaring props in userland.

If overriding slot fallback content is a common scenario, a built-in syntax will definitely help users to build apps with lower overhead on designing this kind of API. And this helps Vue users to understand what is the underlying logic of the template across different Vue projects.

I think the "fallback content" is different with "default content", if we have defined fallback content, any behavior to make the content "empty" should be considered as a hack at first. From this point I agree with @yyx990803 . So here hack with a zero-width space is just good to me. Or you can define a "conditional" fallback content as @fnlctrl provided to set the content empty. Or you never define a fallback content as the default content.
Thanks.

For a more consistent solution, I'd create an empty functional (stateless for better performance) component with a span element, which is completely layout-less, because it's an inline element. Using a p tag can introduce user-agent margin:

<template functional>
  <span></span>
</template>

<script>
export default { name: 'VEmpty' }
</script>

// Usage
<template>
  <v-foo>
    <v-empty></v-empty>
  </v-foo>
</template>

2.4.4 did seem more natural to me. I recently upgraded to 2.5.x and ended up here. :)

@adi518

  1. This is not “completely layout-less” because even empty DOM elements will match CSS selectors like :first-child, :last-child, etc.

  2. A bare <span> element is more performant than a functional component IMO.

  3. <span> element is not always a valid child for a given parent element. Eg. <ul>, <tr>, etc.

A bare <span> element is not consistent. An encapsulated solution is better IMO. If <span> creates a problem, use <i>. That should be valid pretty much everywhere. With component-based development, I suggest refraining from pseudo selectors/elements as their implicitness is a con. In the older days it used to save you some markup, now it is no longer an issue since components reduce the average amount of code you have to write anyway. Instead of pseudo selectors, use classes, which are explicit and give you better control.

<i> is basically <span> with special semantics, it shares the same categories with <span>. Neither of them can be used inside <ul>, <tr> and a lot of other elements.

Instead of pseudo selectors, use classes, which are explicit and give you better control.

Yes you remind me of the old days that I have to support IE6...But what I want is a clean solution that does not prevent developers from leveraging modern technologies such as pseudo classes.

Well, it's opinionated. With a year of developing a library, I didn't find much use for them or sense their absence. Not using <i> in those tags doesn't sound probable. See here.

@yyx990803
Sad that this is closed.
I also would like to be able to clear the default slot content by an empty slot.

e.g. if you have a default "separator"-slot. Sometimes the iterated components may not have any html-tags in between because they break the float css styles. Also it's not clean to just use "empty" tags if it would be more logical to use an empty template.
(and using v-if's is quite verbose)

So if an