Sync selections between a Table view and a List view
The Table view syncs selections automatically via
syncWithAppState
, while the Tiles (List) view uses checkboxes that manually coordinate with AppState.<Component name="Files">
<AppState id="selections" bucket="sharedSelections" initialValue="{{ selectedIds: [] }}" />
<DataSource id="files" url="/api/files" />
<Text>Selected: {selections.value.selectedIds.length} items</Text>
<Tabs>
<TabItem label="Table View">
<TableView data="{files}" />
</TabItem>
<TabItem label="Tiles View">
<TilesView data="{files}" />
</TabItem>
<TabItem label="Debug">
<DebugView />
</TabItem>
</Tabs>
</Component>
<Component name="TableView">
<AppState id="selections" bucket="sharedSelections" />
<Card>
<Table
data="{$props.data}"
rowsSelectable="true"
syncWithAppState="{selections}"
loading="{!$props.data}"
>
<Column bindTo="name" />
<Column bindTo="size" />
<Column bindTo="type" />
</Table>
</Card>
</Component>
<Component name="TilesView">
<AppState id="selections" bucket="sharedSelections" />
<List data="{$props.data}">
<Card>
<HStack verticalAlignment="center">
<Checkbox
initialValue="{selections.value.selectedIds?.includes($item.id) || false}"
onDidChange="(checked) => {
const ids = selections.value.selectedIds || [];
if (checked) {
selections.update({ selectedIds: [...ids, $item.id] });
} else {
selections.update({ selectedIds: ids.filter(id => id !== $item.id) });
}
}"
/>
<VStack>
<Text>{$item.name}</Text>
<Text variant="caption">{$item.size} - {$item.type}</Text>
</VStack>
</HStack>
</Card>
</List>
</Component>
The spread operator
...ids
takes all existing IDs from the array, and creates a new array with those IDs plus the new one.The filter method creates a new array with only items that meet a condition.
<Component name="DebugView">
<AppState id="selections" bucket="sharedSelections" />
<Card>
<VStack>
<Text>selections.value</Text>
<Text variant="code">{JSON.stringify(selections.value, null, 2)}</Text>
</VStack>
</Card>
</Component>
<Component name="Files">
<AppState id="selections" bucket="sharedSelections" initialValue="{{ selectedIds: [] }}" />
<DataSource id="files" url="/api/files" />
<Text>Selected: {selections.value.selectedIds.length} items</Text>
<Tabs>
<TabItem label="Table View">
<TableView data="{files}" />
</TabItem>
<TabItem label="Tiles View">
<TilesView data="{files}" />
</TabItem>
<TabItem label="Debug">
<DebugView />
</TabItem>
</Tabs>
</Component>
<Component name="TableView">
<AppState id="selections" bucket="sharedSelections" />
<Card>
<Table
data="{$props.data}"
rowsSelectable="true"
syncWithAppState="{selections}"
loading="{!$props.data}"
>
<Column bindTo="name" />
<Column bindTo="size" />
<Column bindTo="type" />
</Table>
</Card>
</Component>
<Component name="TilesView">
<AppState id="selections" bucket="sharedSelections" />
<List data="{$props.data}">
<Card>
<HStack verticalAlignment="center">
<Checkbox
initialValue="{selections.value.selectedIds?.includes($item.id) || false}"
onDidChange="(checked) => {
const ids = selections.value.selectedIds || [];
if (checked) {
selections.update({ selectedIds: [...ids, $item.id] });
} else {
selections.update({ selectedIds: ids.filter(id => id !== $item.id) });
}
}"
/>
<VStack>
<Text>{$item.name}</Text>
<Text variant="caption">{$item.size} - {$item.type}</Text>
</VStack>
</HStack>
</Card>
</List>
</Component>
The spread operator
...ids
takes all existing IDs from the array, and creates a new array with those IDs plus the new one.The filter method creates a new array with only items that meet a condition.
<Component name="DebugView">
<AppState id="selections" bucket="sharedSelections" />
<Card>
<VStack>
<Text>selections.value</Text>
<Text variant="code">{JSON.stringify(selections.value, null, 2)}</Text>
</VStack>
</Card>
</Component>