Skip to content

Overcritical vue/valid-template-root rule? #971

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
sebiniemann opened this issue Oct 12, 2019 · 11 comments
Closed

Overcritical vue/valid-template-root rule? #971

sebiniemann opened this issue Oct 12, 2019 · 11 comments

Comments

@sebiniemann
Copy link

sebiniemann commented Oct 12, 2019

Tell us about your environment

  • ESLint version: 6.5.1
  • eslint-plugin-vue version: 5.2.3
  • Node version: 10.16.0

Please show your full configuration:

{
  "env": {
    "browser": true,
    "es6": true,
    "node": true
  },
  "extends": [
    "eslint:recommended",
    "plugin:vue/recommended"
  ],
  "parserOptions": {
    "ecmaVersion": 2019,
    "sourceType": "module"
  },
  "plugins": [
    "vue"
  ]
}

What did you do?

<template>
  <template>
    Hello World
  </template>
</template>

https://mysticatea.github.io/vue-eslint-demo/#eJxVjsEKwjAQRH8l7Lmh4DGIZ+8KXryEZiqBmA2bpFBL/91YEepl4e3bYXahgR3I0LHgmYItON2jUv+k1BkhsLqxBLfpfud3QB1JDchkFpoq+sh64DjW7ONDT3pkadOPZA7d5icbvNO/uBbm0tzakY8OsVz8C9vtF69z+nyakx3QmpKVDGkL5CQArW/g3EXT

My actual use case is something like

<template>
  <template v-if="isValid">
    True
  </template>
  <template v-else>
    False
  </template>
</template>

<script>
export default {
  data() {
    return {
      isValid: false,
    };
  },
};
</script>

where we always use <template> in conjunction with v-for, v-if, ...

https://mysticatea.github.io/vue-eslint-demo/#eJx1kM9KxDAQxl9lmJNCQ8FjXT36Ai576iU0EwnEJEwmxd3Sdzdpu4KIp3y/mW/+ZcEpGsIBT0KfyWuh1zEA/BDMytmXEV2+aO/MiFsa4MyFNmP/bx35TIf7TVf9x/4LKuaJXZKq6StFFjBkdfECS6s0WvTD464BmKRwuBPAsd4Atk3q9vD63N61UlOn/uiPHXLxlHFYcC7Uh6imGGzJLnyoWdnIqh2Nw1O35efWWd1XVRyj1NzaoQuGgry7G23eHc/X1L4zJz1RnZQ0Z+IaoJyYCNdvtNp8aA==

What did you expect to happen?
No error, as Vue compiles without problem.

What actually happened?

[vue/valid-template-root] The template root disallows 'template' elements.

@ota-meshi
Copy link
Member

Thank you for this issue.

Your template will fail to compile on Vue Template Explorer.

image

I think this rule is working correctly.

@sebiniemann
Copy link
Author

sebiniemann commented Oct 17, 2019

Thanks for looking into this 😊

This is interesting. I tested it within our build process, which uses the official vue-template-compiler package and compiles it without failure:

const vueTemplateCompiler = require('vue-template-compiler');

const { render, staticRenderFns } = vueTemplateCompiler.compile(`
<template v-if="isValid">
  True
</template>
<template v-else>
  False
</template>
`);

console.log(render);
console.log(staticRenderFns);

Output:

render:  with(this){return (isValid)?[_v("\n  True\n")]:[_v("\n  False\n")]}
staticRenderFns:  []

After your comment, I further investigated this behaviour and saw that vue-template-compiler will also export warnings besides render and staticRenderFns. Using this, I extracted the same output as you:

Cannot use <template> as component root element because it may contain multiple nodes.

After investigating the compiler's source code, I saw that the warning will always be generated if either <template> or <slot> is present at the root level. Regardless if it proposes an actual problem. The code above for example is fully functional and works as expected within a Vue project.

How about an option for vue/valid-template-root, to allow <template> as root, without having to disable the whole rule altogether? This would be great :). As an enhancement, one could also explicitly test for multiple nodes within the root <template>. If it helps, I'd be happy to submit a pull request for this.

wmfgerrit pushed a commit to wikimedia/mediawiki-extensions-Wikibase that referenced this issue Feb 6, 2020
This should fix all medium-and-above severity security issues reported
by npm audit. The only remaining issue that cannot be fixed by running
`npm upgrade` or `npm audit fix` will be fixed in a follow-up commit.

The rule to enforce a single root in vue templates seems to be a bit
overzealous. This has already been reported upstream in
vuejs/eslint-plugin-vue#971 and was also discussed in
vuejs/eslint-plugin-vue#884 and vuejs/eslint-plugin-vue#986 without
obvious solution that would be applicable here. Solved by adding a not
strictly necessary wrapping span.

Change-Id: I3153c0f45ce53704ef2c02d7e2e2e4f6d67e3fc7
wmfgerrit pushed a commit to wikimedia/mediawiki-extensions that referenced this issue Feb 6, 2020
* Update Wikibase from branch 'master'
  to e7ada5fde5f187fef50badd632676363f322691f
  - Merge "bridge: Upgrade dependencies"
  - bridge: Upgrade dependencies
    
    This should fix all medium-and-above severity security issues reported
    by npm audit. The only remaining issue that cannot be fixed by running
    `npm upgrade` or `npm audit fix` will be fixed in a follow-up commit.
    
    The rule to enforce a single root in vue templates seems to be a bit
    overzealous. This has already been reported upstream in
    vuejs/eslint-plugin-vue#971 and was also discussed in
    vuejs/eslint-plugin-vue#884 and vuejs/eslint-plugin-vue#986 without
    obvious solution that would be applicable here. Solved by adding a not
    strictly necessary wrapping span.
    
    Change-Id: I3153c0f45ce53704ef2c02d7e2e2e4f6d67e3fc7
@mitar
Copy link

mitar commented Mar 9, 2020

Why has this been closed? I do not think it has been fixed?

@robertjbass
Copy link

@sebiniemann I'm using the new Vue 3 "Vite" with
npx create-vite-app <appName>
Since vite/vue3 SFC, can we look at this again? I'm getting tired of changing all of my settings as I switch between projects

@sebiniemann
Copy link
Author

Sorry @mitar I must have missed the notification.

After further discussions over another channel, I closed this issue. While VueJS technically supports if/else templates as root, this (unfortunately) does not seems to be an official feature.

@716green I have not yet read up completely on the new VueJS 3 features. Is this now officially supported in the current VueJS 3 alpha (and probably after that)? Would be great.

@mitar
Copy link

mitar commented May 4, 2020

How is this not an official feature in Vue (before 3)? It was asked through an issue vuejs/vue#3878 and support for it explicitly added vuejs/vue#3887 already in 2016.

@mitar
Copy link

mitar commented May 4, 2020

This is separate from vuejs/vue#4128, which I agree it should not be supported. But v-if an v-else have only one root element always and it is an explicit Vue feature. Please point to any information which shows that it is not such.

@sebiniemann sebiniemann reopened this May 4, 2020
@sebiniemann
Copy link
Author

Thanks for the clarification @mitar
It looks like I've created a bit of a misunderstanding here.

The main difference is that our use case only uses templates for such manipulations (mainly due to a migration from other frameworks that use non-HTML expressions for loops and if statements). And since it can be further rewritten to avoid <template> in this cases, it is fully understandable for me if @ota-meshi decides not to implement this.

As stated last year, after the feedback from @ota-meshi in this thread, the problems lies not within the if/else part, but with the <template> tag.

Technically, everything works fine, especially if there is only one element behind it, as the warning says:

Cannot use <template> as component root element because it **may** contain multiple nodes.

However, eslint-plugin-vue seems to be on the more stricter side of may, even if the actual condition (not having multiple nodes) isn't violated.

@mitar
Copy link

mitar commented May 5, 2020

I see. I in fact missed that this issue is about v-if/v-else in template root in connection with a template tag (inside main template tag). To me the surprising thing is that I am getting this with regular tags. So in my case:

<template>
  <v-row v-if="!indexData">
    ...
  </v-row>
  <custom-component v-else>
    ...
  </custom-component>
</template>

So this is just invalid, no?

@ota-meshi
Copy link
Member

Hi. Sorry for the late reply.

The vue/valid-template-root rule is valid when v-if / v-else is set correctly.
We can check it in the demo.

The aims of vue/valid-template-root rule is to catch the error beforehand in the general framework of Vue.

This rule will report an error as <template> in the root will cause an error in Vue Template Explorer. This is correct behavior.
At this time, we do not have the afford to support other usages, so we do not plan to add optional support.

If you have any other issues, please open a new issue.

@mitar
Copy link

mitar commented May 22, 2020

Awesome, if this works.

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