Skip to content

polish template v-for error report #168

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

Merged
merged 6 commits into from
Sep 1, 2017
Merged
Show file tree
Hide file tree
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
28 changes: 22 additions & 6 deletions lib/rules/valid-v-for.js
Original file line number Diff line number Diff line change
Expand Up @@ -19,34 +19,50 @@ const utils = require('../utils')
* Check whether the given attribute is using the variables which are defined by `v-for` directives.
* @param {ASTNode} vFor The attribute node of `v-for` to check.
* @param {ASTNode} vBindKey The attribute node of `v-bind:key` to check.
* @param {boolean} isChild If checks on child in template[v-for].
* @returns {boolean} `true` if the node is using the variables which are defined by `v-for` directives.
*/
function isUsingIterationVar (vFor, vBindKey) {
function isUsingIterationVar (vFor, vBindKey, isChild) {
if (vBindKey.value == null) {
return false
}
const references = vBindKey.value.references
const variables = vFor.parent.parent.variables

return references.some(reference =>
const used = references.some(reference =>
variables.some(variable =>
variable.id.name === reference.id.name &&
variable.kind === 'v-for'
)
)

if (!isChild || used) {
return used
}
const childFor = utils.getDirective(vBindKey.parent.parent, 'for')
if (!childFor) {
return false
}
const childForRefs = childFor.value.references
return childForRefs.some(cref =>
variables.some(variable =>
cref.id.name === variable.id.name &&
variable.kind === 'v-for'
)
)
}

/**
* Check the given element about `v-bind:key` attributes.
* @param {RuleContext} context The rule context to report.
* @param {ASTNode} vFor The attribute node of `v-for` to check.
* @param {ASTNode} element The element node to check.
* @param {boolean} isChild If element is a child of template[v-for].
*/
function checkKey (context, vFor, element) {
function checkKey (context, vFor, element, isChild) {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

checkKey is not always called with 4 parameters

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

labeled as optional

if (element.name === 'template') {
for (const child of element.children) {
if (child.type === 'VElement') {
checkKey(context, vFor, child)
checkKey(context, vFor, child, true)
}
}
return
Expand All @@ -61,7 +77,7 @@ function checkKey (context, vFor, element) {
message: "Custom elements in iteration require 'v-bind:key' directives."
})
}
if (vBindKey != null && !isUsingIterationVar(vFor, vBindKey)) {
if (vBindKey != null && !isUsingIterationVar(vFor, vBindKey, isChild)) {
context.report({
node: vBindKey,
loc: vBindKey.loc,
Expand Down
9 changes: 9 additions & 0 deletions tests/lib/rules/valid-v-for.js
Original file line number Diff line number Diff line change
Expand Up @@ -82,6 +82,10 @@ tester.run('valid-v-for', rule, {
{
filename: 'test.vue',
code: '<template v-for="x of list">foo<div></div></template>'
},
{
filename: 'test.vue',
code: '<template><div><template v-for="x of list"><div v-for="foo of x" :key="foo"></div></template></div></template>'
}
],
invalid: [
Expand Down Expand Up @@ -179,6 +183,11 @@ tester.run('valid-v-for', rule, {
filename: 'test.vue',
code: '<template><div><template v-for="xin list"><div></div></template></div></template>',
errors: ["'v-for' directives require that attribute value."]
},
{
filename: 'test.vue',
code: '<template><div><template v-for="x of list"><div v-for="foo of y" :key="foo"></div></template></div></template>',
errors: ["Expected 'v-bind:key' directive to use the variables which are defined by the 'v-for' directive."]
}
]
})