Skip to content

Allow if statement under keyed each block when using the animate directive #8680

@brandonmcconnell

Description

@brandonmcconnell

Describe the problem

I get the usual An element that uses the animate directive must be the immediate child of a keyed each block error when attempting to do this:

<script>
	import { scale } from 'svelte/transition';
	import { flip } from 'svelte/animate';

	let values = [1, 2, 3, 4, 5];
	const duration = 300;
</script>

{#each values as value, i (value)}
	{#if value > 2}
		<span in:scale|local={{ duration, delay: i * 10 }} animate:flip={{ duration }}>
			{value}
		</span>
	{/if}
{/each}

REPL: https://svelte.dev/repl/9a63f6ad0066480a93d31729ed959577?version=3.59.1

That doesn't work, but the same logic refactored into a filter of the each'd array does work:

<script>
	import { scale } from 'svelte/transition';
	import { flip } from 'svelte/animate';

	let values = [1, 2, 3, 4, 5];
	const duration = 300;
</script>

{#each values.filter(value => value > 2) as value, i (value)}
	<span in:scale|local={{ duration, delay: i * 10 }} animate:flip={{ duration }}>
		{value}
	</span>
{/each}

REPL: https://svelte.dev/repl/b9a2dec8a0fc474b819e905a79b08b43?version=3.59.1

Describe the proposed solution

Maybe the second is more straightforward for the compiler, but if this restriction could be loosened, I think it would greatly improve the developer experience of working with the animate directive.

Alternatives considered

The only foreseeable workaround would be to continue using the filtered approach which sometimes requires redundant logic, like this:

<script>
	import { scale } from 'svelte/transition';
	import { flip } from 'svelte/animate';

	let values = ['tom', 'frank', 'george'];
	const duration = 300;
</script>

{#each values.filter(name => {
	const upperName = name.toUpperCase();
	return upperName.startsWith('T');
}) as value, i (value)}
	{@const upperName = value.toUpperCase()}
	<span in:scale|local="{{ duration, delay: i * 10 }}" animate:flip="{{ duration }}">
		{upperName}
	</span>
{/each}

REPL: https://svelte.dev/repl/9a63f6ad0066480a93d31729ed959577?version=3.59.1

when the desire was just to do this:

<script>
	import { scale } from 'svelte/transition';
	import { flip } from 'svelte/animate';

	let values = ['tom', 'frank', 'george'];
	const duration = 300;
</script>

{#each values as value, i (value)}
	{@const upperName = value.toUpperCase()}
	{#if upperName.startsWith('T')}
		<span in:scale|local="{{ duration, delay: i * 10 }}" animate:flip="{{ duration }}">
			{upperName}
		</span>
	{/if}
{/each}

Importance

would make my life easier

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions