Merge pull request #122 from sveltejs/each-else

Support {{#each}}-{{else}}
pull/131/head
Rich Harris 8 years ago committed by GitHub
commit f5b78e406c

@ -5,8 +5,11 @@ export default {
enter ( generator, node ) {
const i = generator.counters.each++;
const name = `eachBlock_${i}`;
const elseName = `${name}_else`;
const iterations = `${name}_iterations`;
const renderer = `renderEachBlock_${i}`;
const renderElse = `${renderer}_else`;
const { params } = generator.current;
const listName = `${name}_value`;
@ -21,12 +24,21 @@ export default {
generator.current.initStatements.push( deindent`
var ${name}_value = ${snippet};
var ${iterations} = [];
${node.else ? `var ${elseName} = null;` : ''}
for ( var i = 0; i < ${name}_value.length; i += 1 ) {
${iterations}[i] = ${renderer}( ${generator.current.params}, ${listName}, ${listName}[i], i, component );
${iterations}[i] = ${renderer}( ${params}, ${listName}, ${listName}[i], i, component );
${!isToplevel ? `${iterations}[i].mount( ${anchor}.parentNode, ${anchor} );` : ''}
}
` );
if ( node.else ) {
generator.current.initStatements.push( deindent`
if ( !${name}_value.length ) {
${elseName} = ${renderElse}( ${params}, component );
${!isToplevel ? `${elseName}.mount( ${anchor}.parentNode, ${anchor} );` : ''}
}
` );
}
if ( isToplevel ) {
generator.current.mountStatements.push( deindent`
@ -34,6 +46,13 @@ export default {
${iterations}[i].mount( ${anchor}.parentNode, ${anchor} );
}
` );
if ( node.else ) {
generator.current.mountStatements.push( deindent`
if ( ${elseName} ) {
${elseName}.mount( ${anchor}.parentNode, ${anchor} );
}
` );
}
}
generator.current.updateStatements.push( deindent`
@ -41,10 +60,10 @@ export default {
for ( var i = 0; i < ${name}_value.length; i += 1 ) {
if ( !${iterations}[i] ) {
${iterations}[i] = ${renderer}( ${generator.current.params}, ${listName}, ${listName}[i], i, component );
${iterations}[i] = ${renderer}( ${params}, ${listName}, ${listName}[i], i, component );
${iterations}[i].mount( ${anchor}.parentNode, ${anchor} );
} else {
${iterations}[i].update( changed, ${generator.current.params}, ${listName}, ${listName}[i], i );
${iterations}[i].update( changed, ${params}, ${listName}, ${listName}[i], i );
}
}
@ -54,12 +73,51 @@ export default {
${iterations}.length = ${listName}.length;
` );
if ( node.else ) {
generator.current.updateStatements.push( deindent`
if ( !${name}_value.length && ${elseName} ) {
${elseName}.update( changed, ${params} );
} else if ( !${name}_value.length ) {
${elseName} = ${renderElse}( ${params}, component );
${elseName}.mount( ${anchor}.parentNode, ${anchor} );
} else if ( ${elseName} ) {
${elseName}.teardown( true );
}
` );
}
generator.current.teardownStatements.push( deindent`
for ( var i = 0; i < ${iterations}.length; i += 1 ) {
${iterations}[i].teardown( ${isToplevel ? 'detach' : 'false'} );
}
` );
if ( node.else ) {
generator.current.teardownStatements.push( deindent`
if ( ${elseName} ) {
${elseName}.teardown( ${isToplevel ? 'detach' : 'false'} );
}
` );
}
if ( node.else ) {
generator.push({
useAnchor: false,
name: renderElse,
target: 'target',
localElementDepth: 0,
initStatements: [],
mountStatements: [],
updateStatements: [],
detachStatements: [],
teardownStatements: [],
counter: counter()
});
node.else.children.forEach( generator.visit );
generator.addRenderer( generator.current );
generator.pop();
}
const indexNames = Object.assign( {}, generator.current.indexNames );
const indexName = indexNames[ node.context ] = ( node.index || `${node.context}__index` );
@ -76,7 +134,7 @@ export default {
const contextDependencies = Object.assign( {}, generator.current.contextDependencies );
contextDependencies[ node.context ] = dependencies;
const params = generator.current.params + `, ${listName}, ${node.context}, ${indexName}`;
const blockParams = generator.current.params + `, ${listName}, ${node.context}, ${indexName}`;
generator.push({
useAnchor: false,
@ -92,7 +150,7 @@ export default {
indexNames,
listNames,
params,
params: blockParams,
initStatements: [],
mountStatements: [],

@ -112,7 +112,9 @@ export default function mustache ( parser ) {
else if ( parser.eat( 'else' ) ) {
const block = parser.current();
if ( block.type !== 'IfBlock' ) parser.error( 'Cannot have an {{else}} block outside an {{#if ...}} block' );
if ( block.type !== 'IfBlock' && block.type !== 'EachBlock' ) {
parser.error( 'Cannot have an {{else}} block outside an {{#if ...}} or {{#each ...}} block' );
}
parser.allowWhitespace();
parser.eat( '}}', true );

@ -0,0 +1,17 @@
export default {
data: {
animals: [ 'alpaca', 'baboon', 'capybara' ],
foo: 'something else'
},
html: 'before\n<p>alpaca</p><p>baboon</p><p>capybara</p>\nafter',
test ( assert, component, target ) {
component.set({ animals: [] });
assert.htmlEqual( target.innerHTML, 'before\n<p>no animals, but rather something else</p>\nafter' );
component.set({ foo: 'something other' });
assert.htmlEqual( target.innerHTML, 'before\n<p>no animals, but rather something other</p>\nafter' );
component.set({ animals: ['wombat'] });
assert.htmlEqual( target.innerHTML, 'before\n<p>wombat</p>\nafter' );
}
};

@ -0,0 +1,7 @@
before
{{#each animals as animal}}
<p>{{animal}}</p>
{{else}}
<p>no animals, but rather {{foo}}</p>
{{/each}}
after

@ -0,0 +1,5 @@
{{#each animals as animal}}
<p>{{animal}}</p>
{{else}}
<p>no animals</p>
{{/each}}

@ -0,0 +1,67 @@
{
"html": {
"start": 0,
"end": 84,
"type": "Fragment",
"children": [
{
"start": 0,
"end": 84,
"type": "EachBlock",
"expression": {
"start": 8,
"end": 15,
"type": "Identifier",
"name": "animals"
},
"context": "animal",
"children": [
{
"start": 29,
"end": 46,
"type": "Element",
"name": "p",
"attributes": [],
"children": [
{
"start": 32,
"end": 42,
"type": "MustacheTag",
"expression": {
"start": 34,
"end": 40,
"type": "Identifier",
"name": "animal"
}
}
]
}
],
"else": {
"children": [
{
"attributes": [],
"children": [
{
"data": "no animals",
"end": 70,
"start": 60,
"type": "Text"
}
],
"end": 74,
"name": "p",
"start": 57,
"type": "Element"
}
],
"end": 75,
"start": 55,
"type": "ElseBlock"
}
}
]
},
"css": null,
"js": null
}
Loading…
Cancel
Save