Skip to content
This repository has been archived by the owner on Feb 26, 2023. It is now read-only.

Implementing each custom attribute for all elements #521

Open
pournasserian opened this issue Sep 21, 2022 · 13 comments
Open

Implementing each custom attribute for all elements #521

pournasserian opened this issue Sep 21, 2022 · 13 comments
Assignees
Milestone

Comments

@pournasserian
Copy link
Contributor

Similar to if processor, that would be helpful to have each:

Here is a sample code:

<div each={items} let:item let:index>
	{index} - {item.name} ({item.country})
</div>

Here is a simple implementation for more clarification: repl

Any other ideas?

@pournasserian pournasserian changed the title Implementing each custom attribute for all elements Implementing each custom attribute for all elements Sep 21, 2022
@pournasserian pournasserian added this to the Milestone 3 milestone Sep 21, 2022
@TheHadiAhmadi
Copy link
Collaborator

Control Flow section of solidjs is interesing control-flow especially For, ErrorBoundary and Suspense components.

which we can achieve some of those features with preprocessors

@pournasserian
Copy link
Contributor Author

Control Flow section of solidjs is interesing control-flow especially For, ErrorBoundary and Suspense components.

which we can achieve some of those features with preprocessors

That's nice. Svelte has similar features with different way (code blocks).

Please provide a final code which end-developers should use. Using each in the same line of HTML element or Svelte component will reduce 2 lines of codes in template.

@TheHadiAhmadi
Copy link
Collaborator

Here is another example:

<ul>
  <li each={COLORS} let:index let:item={color}>{index}- {color}</li>
</ul>

how we should implement keyed each blocks? do we need to support it?

<ul>
  {#each COLORS as color, index (TODO)} <!-- should we support keyed each? -->
    <li>{index}- {item}</li>
  {/each}
</ul>

@pournasserian
Copy link
Contributor Author

@TheHadiAhmadi here is another example if you want to set variable to avoid conflict in nested each loop:
repl

@TheHadiAhmadi
Copy link
Collaborator

@pournasserian yes that is okay, how should we support keyed each blocks?

{#each items as item, index (item.id)}
  <li>{index} - {item.name}</li>
{/each}

This is my solution

<Each items={items} _key="item.id" let:item let:index (item.id}>
  <li>{index} - {item.name}</li>
</Each>

Do you have better ideas to support keys? Do we need that?

@pournasserian
Copy link
Contributor Author

@TheHadiAhmadi how about this:

<Each items={items} let:item let:index (item.id}>
  <li>{index} - {item.name}</li>
</Each>

@TheHadiAhmadi
Copy link
Collaborator

@pournasserian this is good idea.

but it is not standard svelte syntax and I don't know is it possible to do this without having error while development or not? (in production we will not have any error)
we can test this when we started working on preprocessor.

another thing that we should consider is {#each} vs <Each/>, I think we don't need Each component and it is easier to go with each block.

also we can save some bytes of output's js code. as you can see in first repl, Each component is compiled to 184 lines of javascript code.

@pournasserian
Copy link
Contributor Author

@TheHadiAhmadi this idea is just an example and I am thinking to write eachProcessor similar to if.

Then, we generate the code and inject into existing like what we did in ifProcessor.

@TheHadiAhmadi
Copy link
Collaborator

I will work on a preprocessor which will change EXAMPLE1 to EXAMPLE2

EXAMPLE1:

<script>
  let items=["zero", "one", "two", "three"];
</script>

<!-- First -->
<div each={items} let:item let:index>
  {index} - {item}
</div>

<!-- Second -->
<ul>
  <li each={items} let:item={myNumber} let:index={myIndex}>
    {myIndex}: {myNumber}
  </li>
</ul>

<!-- Third -->
<ul>
  <li each={[
    {id: 'random-id-1', name: 'one'}, 
    {id: 'random-id-2', name: 'two'}, 
    {id: 'random-id-3', name: 'three'}
  ]} let:item (item.id)>
    {item.id}: {item.name}
  </li>
</ul>

EXAMPLE2:

<script>
  let items=["zero", "one", "two", "three"];
</script>

<!-- First -->
{#each items as item, index}
  <div>
    {index} - {item}
  </div>
{/each}

<!-- Second -->
<ul>
  {#each items as myNumber, myIndex}
    <li>
      {myIndex}: {myNumber}
    </li>
  {/each}
</ul>

<!-- Third -->
<ul>
  {#each [
    {id: 'random-id-1', name: 'one'}, 
    {id: 'random-id-2', name: 'two'}, 
    {id: 'random-id-3', name: 'three'}
  ] as item (item.id)}
    <li>
      {item.id}: {item.name}
    </li>
  {/each}
</ul>

@TheHadiAhmadi TheHadiAhmadi linked a pull request Sep 26, 2022 that will close this issue
@TheHadiAhmadi
Copy link
Collaborator

TheHadiAhmadi commented Sep 26, 2022

We need to find a way to add custom types for components.

for example for each prop we need to add item and index props for default slots of ALL components and DOM Elements.

<script lang="ts">
	import { get_current_component, getContext, setContext } from 'svelte/internal'
	import { writable } from 'svelte/store'

	import { nanoid } from 'nanoid'

	import { forwardEventsBuilder } from '$lib/directives'
	import { classname } from '$lib/utils'

+	type T = $$Generic

+	interface $$Props {
+		each?: T[] // We need to know type of each item (T)
+		id?: string
+		open?: boolean
+		[x: string]: any
+	}

+	interface $$Slots {
+		default: { item: T; index: number }
+	}

        export let open: boolean = false;

        export let id: string = nanoid(5);

        ....

</script>

<div use:forwardEvents {...$$restProps} class={classes}>
	<slot />
</div>

github.com/svelteuidev/svelteui/packages/svelteui-core/src/components/Grid/Grid.svelte

we can also do something like this to avoid duplication:

	type T = $$Generic

	interface $$Props {
		each?: T[]
		id?: string
		open?: boolean
		[x: string]: any
	}

	interface $$Slots {
		default: { item: T; index: number }
	}

        export let open: $$Props['open'] = false;

        export let id: $$Props['id'] = nanoid(5);

@TheHadiAhmadi
Copy link
Collaborator

TheHadiAhmadi commented Sep 26, 2022

another usage of $$Props will be for Component Inheritance and we will not have this problem

@TheHadiAhmadi
Copy link
Collaborator

@TheHadiAhmadi
Copy link
Collaborator

@pournasserian pournasserian modified the milestones: Milestone 3, Milestone 4 Oct 3, 2022
@pournasserian pournasserian modified the milestones: Milestone 4, 2023-Q1 Jan 2, 2023
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.