-
-
Notifications
You must be signed in to change notification settings - Fork 33.7k
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
Allow for <component> to be a conditional wrapper ie. only render children. #12033
Comments
This can be achieved through a render function. It should be a functional component in Vue 2 but can be anything in Vue 3. If you think something like this is worth pursuing in vue core rather than an external library, you can open a PR on the vuejs/rfcs repository |
I tried and so have others but so far nobody has cracked it. All solutions are workarounds with edge cases but none do it cleanly. What i tried here: was: export default {
functional: true,
props: ['tag'],
render(h, context) {
const { children, props, data } = context
// The wrapper element itself becomes the html element/component.
if (props.tag) {
return h(props.tag, data, children)
} else {
// And if the tag is false than it only renders children
return children
}
},
} <wrapper :tag=" shout ? 'h1' : false ">
Am I shouting?
</wrapper> But I have difficulties making Any advice on what the best approach would be? |
I was suprised to find out this is not supported by Vue. We need this! 😄 |
If something like this does eventually get implemented, I think it would make a lot more sense to use a directive, analogous to the
|
Why was this closed, this is a good feature to have. Edit: To be clear, I don't think this is the biggest deal in the world, but it does seem in line with the level of the other helpful conveniences Vue does. My (annoying) solution is to have a special <template>
<component :is="tag" v-if="wrap">
<slot />
</component>
<slot v-else />
</template>
<script setup lang="ts">
interface Props {
tag: string;
wrap: boolean;
}
defineProps<Props>();
</script> Also, I'd lean towards OP's solution of using vue's existing fragment <template>
<component :is="shouldWrap ? 'div' : 'template'">
some content
</component>
</template> (The above is a proposal, it doesn't currently work) |
FYI, this has since been opened as an RFC: vuejs/rfcs#449 |
Is there any news on this? The conditional wrapper feature would be really useful and I'm wondering whether someone already found a solution for this. Either as a custom directive or over the |
Any status update? :) |
We'll be glad to hear any news about solving this problem. :3 |
I've said it somewhere else, but why not here again: <script>
// inspired by a workaround for missing "optional wrapper" functionality in vue
// see: https://github.com/vuejs/rfcs/discussions/448#discussioncomment-5487435
export default {
name: 'Fragment',
render(h) {
if (this.$slots && this.$slots.default) {
return this.$slots.default;
}
return null;
},
};
</script> Usage: <component
:is="isLink ? 'a' : 'Fragment'"
:href="someLinkComputed"
>
I can even be plain text!
</component> |
You can even shorten your code to this:
With this, you can use it very similar to your prefered proposal:
|
A workaround is to use the <template>
<component :is="condition ? Wrapper : Transition">
<span>Child</span>
</component>
</template>
<script setup>
import { Transition } from 'vue';
</script> |
Looks like a neat solution for Vue 3 |
I've created a new RFC to address this feature request. Please join the discussion here if you are interested. |
What problem does this feature solve?
This use case is often called a conditional wrapper .
There sometimes is a need to wrap an element in a link or other elements for styling.
But instead of making multiple similar components or providing a placeholder tag like
div
.It would be great to be able to simply leave out the wrapping. This is important since sometimes a even simple 'div' wrapper can break styling as well/ would need extra consideration/ work/ moving parts.
What does the proposed API look like?
I think the most clean and practical way for programmatic use would be to use the
is
prop.Either by passing in a falsy value, or by passing in 'template', a tag that doesn't render in the html.
<component :is="false"><span>Child</span></component>
<span>Child</span>
<component :is="'template'"><span>Child</span></component>
<span>Child</span>
The text was updated successfully, but these errors were encountered: