a2ui-project / a2ui-project/a2ui
[spec] children are unkeyed, making it impossible to move children correctly
- Lenguaje dominante
- TypeScript
- Estrellas
- 16.4k
- Forks
- 1.3k
- Merge medio
- 2 d 13 h
- PR fusionados (30 d)
- 134
Descripción
## Problem
Consider this example from https://a2ui.org/specification/v0.9.1-a2ui/#collection-scopes-relative-paths:
Data model:
```
{
"company": "Acme Corp",
"employees": [
{"name": "Alice", "role": "Engineer"},
{"name": "Bob", "role": "Designer"}
]
}
```
Component definition:
```
{
"id": "employee_list",
"component": "List",
"children": {
"path": "/employees",
"componentId": "employee_card_template"
}
},
{
"id": "employee_card_template",
"component": "Column",
"children": ["name_text", "company_text"]
},
{
"id": "name_text",
"component": "Text",
"text": { "path": "name" }
},
{
"id": "company_text",
"component": "Text",
"text": { "path": "/company" }
}
```
A list of employees is renderer using the "employee_card_template" template component. On the first render everything is correct. However, consider a data update that swaps Alice and Bob:
```
{
"company": "Acme Corp",
"employees": [
{"name": "Bob", "role": "Designer"}
{"name": "Alice", "role": "Engineer"},
]
}
```
Because `List` children are unkeyed by anything, the data for "Bob" will flow into the card that used to render "Alice" and vice versa. This may produce correct visual result in basic (e.g. read-only) cases. However, this breaks in the following situations:
* If a screen reader focus is focused on Bob, instead of the focus moving with the widget to its new location, the data underneath the screen reader focus will unexpectedly be replaced with Alice. There will also be no screen reader notification to the user about the order change.
* If the user made a selection (e.g. on the web), that selection will be lost.
* If employee cards are editable the editing state may get corrupted, or simply confuse the user.
* If employee card widgets are stateful, their state will not move to a new location in the list, but instead will receive data for a wrong employee, which could violate some business rules.
## Proposal
The data optionally supplies an identifier:
```
{
"company": "Acme Corp",
"employees": [
{"id": "123", "name": "Bob", "role": "Designer"}
{"id": "234", "name": "Alice", "role": "Engineer"},
]
}
```
The list provides the property name that should be used as the child key, and the runtime applies it to every child widget:
```
{
"id": "employee_list",
"component": "List",
"children": {
"path": "/employees",
"componentId": "employee_card_template",
"key": "id" // NEW!
}
}
```
Now that widgets are keyes, the respective UI framework can move the widgets around preserving their state.
Guía de contribución
Evaluación
Este issue todavía no se ha evaluado.