Subscribe on changes!

Compiler not allowing correct usage of <transition-group> keys

avatar
Feb 4th 2022

Version

3.2.29

Reproduction link

sfc.vuejs.org/

Steps to reproduce

Open the reproduction code.

What is expected?

Code should compile and transitions should work fluently when clicking the buttons.

What is actually happening?

It will not compile because of the key property on the group headings:

SyntaxError: <template v-for> key should be placed on the <template> tag.

App.vue
19 |    <transition-group name="cell" tag="div" class="grid">
20 |      <template v-for="group in groups" :key="group.id">
21 |        <h2 :key="`title-${group.id}`">{{ group.name }}</h2>
   |            ^^^^^^^^^^^^^^^^^^^^^^^^^^
22 |        <div v-for="letter in group.letters" :key="letter">{{ letter }}</div>
23 |      </template>

Removing the key will throw a warning:

 at <TransitionGroupname="cell"tag="div"class="grid">

This warning is correct, because without a key the transitions will not work as expected when adding or removing items from the groups array.


There are a couple of similar issues (#4718, #5152), but they are not duplicates of this one since they are focusing on the warning when a key is not used. But in this case, a key is needed but the code won't compile, even though it is valid code.

avatar
Feb 4th 2022

possible workaround sfc

  <transition-group name="cell" tag="div" class="grid">
    <template v-for="group in groups" :key="group.id">

      <template v-if=true >
        <h2   :key="`title-${group.id}`">{{ group.name }}</h2>
        <div v-for="letter in group.letters" :key="letter" class="item">{{ letter }}</div>
      </template>


    </template>
  </transition-group>
avatar
Feb 4th 2022

Duplicate of #4718

avatar
Feb 4th 2022

Thank you @lidlanca for the workaround, it works well but is indeed a workaround. As already mentioned, this is not a duplicate since the previous issue addresses the console warning - however the console warning isn't a bug but the compiler error is, and it cannot be suppressed or ignored (unlike the warning).

avatar
Feb 4th 2022

issues are related and revolve around the same base bug

#4718 expects that there will be no warning, since the fragment is keyed, and it doesn't try to key the fragment nodes. #5360 based on the same warning, try to address it, by keying individual fragment nodes manually, but fail due to syntax error

However this issue exposes an additional bug

There is technically no reason for key in a child node of a v-for fragment to be considered a syntax error. especially for multi nodes fragment

this should be valid code

  <template v-for="item in items" :key="item.i">
      <h1>chart</h1>
      <chart :key="refresh[item.id]"></chart>
  </template>

independent of <transition-group>

avatar
Feb 6th 2022

@LinusBorg

I've been able to remedy this issue by removing the block of code that validates this specific condition.

Line 155 of errors.ts: [ErrorCodes.X_V_FOR_TEMPLATE_KEY_PLACEMENT]: `<template v-for> key should be placed on the <template> tag.`,

Line 121 of vFor.ts:

        // check <template v-for> key placement
        if ((__DEV__ || !__BROWSER__) && isTemplate) {
          node.children.some(c => {
            if (c.type === NodeTypes.ELEMENT) {
              const key = findProp(c, 'key')
              if (key) {
                context.onError(
                  createCompilerError(
                    ErrorCodes.X_V_FOR_TEMPLATE_KEY_PLACEMENT,
                    key.loc
                  )
                )
                return true
              }
            }
          })
        }

Before I make a PR, I just wanted to confirm that this is actually an issue and that simply removing this code is a satisfactory solution.

It looks like this was intentionally added by @yyx990803 back in 2020: https://github.com/vuejs/core/commit/b0d01e9db9ffe5781cce5a2d62c8552db3d615b0

dx(compiler-core): warn on