Skip to content

noVueUselessTemplateAttributes (HTML)

Language HTML
biome.json
{
"linter": {
"rules": {
"nursery": {
"noVueUselessTemplateAttributes": "error"
}
}
}
}

Disallow attributes and directives that have no effect on <template> elements.

Inside a Vue template, a <template> element with v-if, v-else-if, v-else, v-for, or v-slot (or its # shorthand) is only a wrapper: Vue renders its content, but not the <template> element itself. Any other attribute or directive on it, such as class, ref, :title, or @click, has nowhere to go, so Vue ignores it.

Move the attribute or directive to an element inside the <template>, or remove it.

This rule doesn’t report:

  • key, :key, or v-bind:key, which Vue uses to tell the rendered items apart.
  • v-memo on a <template> that has v-for, which Vue uses to skip updating unchanged items.
  • v-once on a <template> that has v-if, v-else-if, v-else, or v-for, which makes Vue render the content only once.
  • Any attribute on a <template> that has none of the directives listed above. Vue keeps such an element as a regular HTML <template> element, so its attributes aren’t ignored.
<template>
<template v-if="visible" class="heading">Title</template>
</template>
code-block.vue:2:28 lint/nursery/noVueUselessTemplateAttributes ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━

✖ This attribute has no effect on a <template> element.

1 │ <template>
> 2 │ <template v-if="visible" class="heading">Title</template>
│ ^^^^^^^^^^^^^^^
3 │ </template>
4 │

ℹ Vue doesn't render a <template> element that has v-if, v-else-if, v-else, v-for, or v-slot, only its content, so it ignores this.

ℹ Move it to an element inside the <template>, or remove it.

ℹ This rule belongs to the nursery group, which means it is not yet stable and may change in the future. Visit https://biomejs.dev/linter/#nursery for more information.

<template>
<template v-for="item in items" :title="item.name">{{ item.name }}</template>
</template>
code-block.vue:2:35 lint/nursery/noVueUselessTemplateAttributes ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━

✖ This directive has no effect on a <template> element.

1 │ <template>
> 2 │ <template v-for="item in items" :title="item.name">{{ item.name }}</template>
│ ^^^^^^^^^^^^^^^^^^
3 │ </template>
4 │

ℹ Vue doesn't render a <template> element that has v-if, v-else-if, v-else, v-for, or v-slot, only its content, so it ignores this.

ℹ Move it to an element inside the <template>, or remove it.

ℹ This rule belongs to the nursery group, which means it is not yet stable and may change in the future. Visit https://biomejs.dev/linter/#nursery for more information.

<template>
<MyList>
<template #item="{ name }" @click="select">{{ name }}</template>
</MyList>
</template>
code-block.vue:3:32 lint/nursery/noVueUselessTemplateAttributes ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━

✖ This directive has no effect on a <template> element.

1 │ <template>
2 │ <MyList>
> 3 │ <template #item="{ name }" @click="select">{{ name }}</template>
│ ^^^^^^^^^^^^^^^
4 │ </MyList>
5 │ </template>

ℹ Vue doesn't render a <template> element that has v-if, v-else-if, v-else, v-for, or v-slot, only its content, so it ignores this.

ℹ Move it to an element inside the <template>, or remove it.

ℹ This rule belongs to the nursery group, which means it is not yet stable and may change in the future. Visit https://biomejs.dev/linter/#nursery for more information.

<template>
<template v-if="visible">
<h1 class="heading">Title</h1>
</template>
<template v-else-if="loading">Loading</template>
<template v-else v-once>Hidden</template>
<template v-for="item in items" :key="item.id" v-memo="[item.name]">
<span :title="item.name">{{ item.name }}</span>
</template>
<MyList>
<template #item="{ name }">{{ name }}</template>
</MyList>
<template class="heading" ref="content">Content</template>
</template>