Skip to content
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鈥檒l occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat: make repeat directive optionally accept a key #6919

Open
sknoslo opened this issue Mar 1, 2024 · 0 comments
Open

feat: make repeat directive optionally accept a key #6919

sknoslo opened this issue Mar 1, 2024 · 0 comments
Labels
area:fast-element Pertains to fast-element status:needs-investigation Needs additional investigation

Comments

@sknoslo
Copy link
Contributor

sknoslo commented Mar 1, 2024

馃檵 Feature Request

Add an optional key to the repeat directive, so that repeat can map a DOM node to a specific item when updating views. Similar to how React or Lit work. This would be beneficial for a couple of reasons:

  1. DOM nodes used within a repeat can maintain their own internal state.
  2. Assistive technology, such as a screen reader, will be able to better understand when content has changed.
  3. Potentially less expensive for some operations?

馃 Expected Behavior

When an array is sorted, or items are added or removed, existing DOM nodes should only be reused for an item with the same key. New DOM nodes should be created for keys that did not previously exist, and DOM nodes should be removed for keys that no longer exist. DOM nodes should never be reused for items with different keys.

馃槸 Current Behavior

When an array is sorted, or items are added or removed, existing DOM nodes are reused just based on position, and the nodes do not map 1-to-1 with the array elements.

馃拋 Possible Solution

Add a optional key function to the repeat directive. Maintain a map of keys -> DOM nodes, and make updates accordingly. Might look something like:

repeat(
  x => x.items,
  html`<div>${item.uniqueId}</div>`,
  { keyFn: (item) => item.uniqueId }
)

Adding a separate "keyed repeat" directive could also be a good option if it makes more sense to keep the behavior distinct.

馃敠 Context

I was building a notification component that could stack alerts to display for a short time. These elements had role="alert" so that a screen reader would announce them when they showed up. But, because nodes are recycled, as new alerts show up or were dismissed, the contents of existing nodes change and the screen reader announces them again, as if they are actually new.

I had to fall back to manually managing the DOM instead of using a template with the repeat directive.

馃捇 Examples

Comparison of behavior between Lit and FAST on StackBlitz. This is a contrived example where a parent element renders a list of numbers in a child element, and the color of the child element can be toggled. This toggle state is owned by each child element. If you toggle the first (or last) item in the list, and then reverse the list, you'll see how the behavior differs.

@sknoslo sknoslo added the status:triage New Issue - needs triage label Mar 1, 2024
@chrisdholt chrisdholt added status:needs-investigation Needs additional investigation area:fast-element Pertains to fast-element and removed status:triage New Issue - needs triage labels May 2, 2024
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
area:fast-element Pertains to fast-element status:needs-investigation Needs additional investigation
Projects
None yet
Development

No branches or pull requests

2 participants