Skip to content

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

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

Closed
brandonmcconnell opened this issue Jun 1, 2023 · 2 comments

Comments

@brandonmcconnell
Copy link
Contributor

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

@brandonmcconnell
Copy link
Contributor Author

brandonmcconnell commented Jun 1, 2023

In my particular situation now, the redundancy is a bit expensive too, as it requires doing a map lookup on each iteration, twice now:

Having to use this:

Instead of this:

@dummdidumm
Copy link
Member

Closing in favor of #7209

@dummdidumm dummdidumm closed this as not planned Won't fix, can't repro, duplicate, stale Nov 3, 2024
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants