Skip to content

Commit

Permalink
Fix nested x-for loop scoping
Browse files Browse the repository at this point in the history
  • Loading branch information
calebporzio committed Mar 30, 2020
1 parent db3c5a5 commit 67970f2
Show file tree
Hide file tree
Showing 6 changed files with 59 additions and 9 deletions.
6 changes: 3 additions & 3 deletions dist/alpine-ie11.js
Original file line number Diff line number Diff line change
Expand Up @@ -5349,7 +5349,7 @@
return !isNaN(subject);
}

function handleForDirective(component, el, expression, initialUpdate) {
function handleForDirective(component, el, expression, initialUpdate, extraVars) {
var _this = this;

if (el.tagName.toLowerCase() !== 'template') console.warn('Alpine: [x-for] directive should only be added to <template> tags.');
Expand All @@ -5369,7 +5369,7 @@
// empty, effectively hiding it.
items = [];
} else {
items = component.evaluateReturnExpression(el, bunch);
items = component.evaluateReturnExpression(el, bunch, extraVars);
} // As we walk the array, we'll also walk the DOM (updating/creating as we go).


Expand Down Expand Up @@ -6410,7 +6410,7 @@
break;

case 'for':
handleForDirective(this, el, expression, initialUpdate);
handleForDirective(this, el, expression, initialUpdate, extraVars);
break;

case 'cloak':
Expand Down
6 changes: 3 additions & 3 deletions dist/alpine.js
Original file line number Diff line number Diff line change
Expand Up @@ -395,7 +395,7 @@
return !isNaN(subject);
}

function handleForDirective(component, el, expression, initialUpdate) {
function handleForDirective(component, el, expression, initialUpdate, extraVars) {
if (el.tagName.toLowerCase() !== 'template') console.warn('Alpine: [x-for] directive should only be added to <template> tags.');
const {
single,
Expand All @@ -412,7 +412,7 @@
// empty, effectively hiding it.
items = [];
} else {
items = component.evaluateReturnExpression(el, bunch);
items = component.evaluateReturnExpression(el, bunch, extraVars);
} // As we walk the array, we'll also walk the DOM (updating/creating as we go).


Expand Down Expand Up @@ -1501,7 +1501,7 @@
break;

case 'for':
handleForDirective(this, el, expression, initialUpdate);
handleForDirective(this, el, expression, initialUpdate, extraVars);
break;

case 'cloak':
Expand Down
19 changes: 19 additions & 0 deletions examples/index.html
Original file line number Diff line number Diff line change
Expand Up @@ -246,6 +246,25 @@
</td>
</tr>

<tr>
<td>Nested x-for</td>
<td>
<div x-data="{ foos: [{bars: [{bobs: ['one', 'two']}, {bobs: ['three', 'four']}]}, {bars: [{bobs: ['five', 'six']}, {bobs: ['seven', 'eight']}]}] }">
<template x-for="foo in foos">
<div>
<template x-for="bar in foo.bars">
<div>
<template x-for="bob in bar.bobs">
<span x-text="bob"></span>
</template>
</div>
</template>
</div>
</template>
</div>
</td>
</tr>

<tr>
<td>Transitions</td>
<td>
Expand Down
2 changes: 1 addition & 1 deletion src/component.js
Original file line number Diff line number Diff line change
Expand Up @@ -275,7 +275,7 @@ export default class Component {
break;

case 'for':
handleForDirective(this, el, expression, initialUpdate)
handleForDirective(this, el, expression, initialUpdate, extraVars)
break;

case 'cloak':
Expand Down
4 changes: 2 additions & 2 deletions src/directives/for.js
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import { transitionIn, transitionOut, getXAttrs } from '../utils'

export function handleForDirective(component, el, expression, initialUpdate) {
export function handleForDirective(component, el, expression, initialUpdate, extraVars) {
if (el.tagName.toLowerCase() !== 'template') console.warn('Alpine: [x-for] directive should only be added to <template> tags.')

const { single, bunch, iterator1, iterator2 } = parseFor(expression)
Expand All @@ -13,7 +13,7 @@ export function handleForDirective(component, el, expression, initialUpdate) {
// empty, effectively hiding it.
items = []
} else {
items = component.evaluateReturnExpression(el, bunch)
items = component.evaluateReturnExpression(el, bunch, extraVars)
}

// As we walk the array, we'll also walk the DOM (updating/creating as we go).
Expand Down
31 changes: 31 additions & 0 deletions test/for.spec.js
Original file line number Diff line number Diff line change
Expand Up @@ -288,3 +288,34 @@ test('listeners in loop get fresh iteration data even though they are only regis

await wait(() => { expect(document.querySelector('h1').innerText).toEqual('bar') })
})

test('nested x-for', async () => {
document.body.innerHTML = `
<div x-data="{ foos: [ {bars: ['bob', 'lob']} ] }">
<button x-on:click="foos = [ {bars: ['bob', 'lob']}, {bars: ['law']} ]"></button>
<template x-for="foo in foos">
<h1>
<template x-for="bar in foo.bars">
<h2 x-text="bar"></h2>
</template>
</h1>
</template>
</div>
`

Alpine.start()

await wait(() => { expect(document.querySelectorAll('h1').length).toEqual(1) })
await wait(() => { expect(document.querySelectorAll('h2').length).toEqual(2) })

expect(document.querySelectorAll('h2')[0].innerText).toEqual('bob')
expect(document.querySelectorAll('h2')[1].innerText).toEqual('lob')

document.querySelector('button').click()

await wait(() => { expect(document.querySelectorAll('h2').length).toEqual(3) })

expect(document.querySelectorAll('h2')[0].innerText).toEqual('bob')
expect(document.querySelectorAll('h2')[1].innerText).toEqual('lob')
expect(document.querySelectorAll('h2')[2].innerText).toEqual('law')
})

0 comments on commit 67970f2

Please sign in to comment.