Skip to content

Commit c0f99dc

Browse files
committed
#6774 sourceId concept
1 parent 3515c0e commit c0f99dc

1 file changed

Lines changed: 86 additions & 1 deletion

File tree

learn/guides/Collections.md

Lines changed: 86 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,92 @@ The `Neo.collection.Base` class is the foundation for all collections in Neo.mjs
1717
- **`map_`**: A `Map` object that stores a key-value pair for each item, allowing for fast lookups by a unique `keyProperty`.
1818
- **`keyProperty`**: By default, this is set to `'id'`, meaning each item in the collection should have a unique `id` property. This is crucial for the `map_` to function correctly.
1919
- **`autoSort`**: If set to `true`, the collection will automatically sort its items when new ones are added or inserted, based on the configured sorters.
20-
- **`sourceId_`**: Collections can be linked to a source collection. Changes in the source collection will be reflected in the dependent collection. This is particularly useful for creating filtered or sorted views of a larger dataset without duplicating the data.
20+
- **`sourceId_`**: Collections can be linked to a source collection. This is a powerful feature where a collection automatically mirrors the data mutations (additions, removals, reordering) of another collection. This is particularly useful for creating filtered or sorted views of a larger dataset without duplicating the data.
21+
22+
### The `sourceId` Concept and Real-World Use Cases
23+
24+
The `sourceId` configuration allows you to create "derived" or "linked" collections that automatically stay in sync with a "source" collection. This is achieved by the dependent collection listening to the `mutate` event of its source. Any changes to the source collection's items are automatically propagated to the dependent collection.
25+
26+
**Real-World Use Cases:**
27+
28+
1. **Master-Detail Views:** Display a master list (source collection) and a filtered or sorted subset of that data in a detail view (dependent collection). Changes in the master list automatically update the detail view.
29+
2. **Multiple Synchronized Components:** On a dashboard, multiple widgets might display different views (filtered, sorted, or transformed) of the same underlying dataset. A central source collection ensures all widgets remain consistent.
30+
3. **Data Transformation Pipelines:** Chain collections together, where the output of one collection (as a source) becomes the input for the next, allowing for complex data processing flows.
31+
32+
This mechanism significantly reduces boilerplate code for data synchronization and ensures data consistency across your application.
33+
34+
**Advanced Use Case: Grid and ComboBox with Shared Data**
35+
36+
Consider a scenario where you have a large dataset (e.g., a list of products) that needs to be displayed in a grid, and a subset of that data needs to be available in a combobox picker list.
37+
38+
If you were to use a single collection for both, typing into the combobox's input field to filter its options would inadvertently filter the data displayed in your grid, which is typically not the desired behavior.
39+
40+
The `sourceId` concept provides an elegant solution:
41+
42+
1. **Master Store (Collection)**: Create a primary `Neo.collection.Base` instance (acting as your data store) that fetches the complete product list from a backend. This collection is not directly bound to any UI component.
43+
2. **Grid Store (Child Collection)**: Create a second `Neo.collection.Base` instance for your grid. Set its `sourceId` to the ID of your master store. This grid store will automatically receive all data and mutations from the master. It can then apply its own sorting or filtering (e.g., to display only "in-stock" items) without affecting the master or other child collections.
44+
3. **ComboBox Store (Child Collection)**: Create a third `Neo.collection.Base` instance for your combobox's picker list. Set its `sourceId` to the ID of your master store. This combobox store can then apply its own filters (e.g., based on user input in the combobox field) and sorters, completely independently of the grid store or the master store.
45+
46+
```javascript
47+
import Collection from '../../src/collection/Base.mjs';
48+
import Filter from '../../src/collection/Filter.mjs';
49+
50+
// 1. Master Store: Fetches data from backend (simulated)
51+
const masterProductsStore = Neo.create(Collection, {
52+
id: 'masterProductsStore',
53+
items: [
54+
{id: 1, name: 'Laptop', category: 'Electronics', price: 1200, inStock: true},
55+
{id: 2, name: 'Mouse', category: 'Electronics', price: 25, inStock: true},
56+
{id: 3, name: 'Keyboard', category: 'Electronics', price: 75, inStock: false},
57+
{id: 4, name: 'Monitor', category: 'Electronics', price: 300, inStock: true},
58+
{id: 5, name: 'Desk Chair', category: 'Furniture', price: 150, inStock: true},
59+
{id: 6, name: 'Webcam', category: 'Electronics', price: 50, inStock: false}
60+
]
61+
});
62+
63+
// 2. Grid Store: Displays all in-stock electronics, sorted by price
64+
const gridStore = Neo.create(Collection, {
65+
id: 'gridStore',
66+
sourceId: 'masterProductsStore', // Linked to master
67+
filters: [
68+
{property: 'inStock', value: true},
69+
{property: 'category', value: 'Electronics'}
70+
],
71+
sorters: [
72+
{property: 'price', direction: 'ASC'}
73+
]
74+
});
75+
76+
// 3. ComboBox Store: Filters based on user input (e.g., 'web')
77+
const comboBoxStore = Neo.create(Collection, {
78+
id: 'comboBoxStore',
79+
sourceId: 'masterProductsStore', // Linked to master
80+
filters: [
81+
// This filter would be dynamically updated by the combobox input
82+
{property: 'name', operator: 'like', value: 'web'}
83+
]
84+
});
85+
86+
console.log('Master Store Count:', masterProductsStore.getCount()); // Output: 6
87+
console.log('Grid Store Count (in-stock electronics):', gridStore.getCount()); // Output: 3 (Laptop, Mouse, Monitor)
88+
console.log('ComboBox Store Count (name like "web"):', comboBoxStore.getCount()); // Output: 1 (Webcam)
89+
90+
// Simulate adding a new product to the master store
91+
masterProductsStore.add({id: 7, name: 'Headphones', category: 'Electronics', price: 100, inStock: true});
92+
93+
console.log('Master Store Count after add:', masterProductsStore.getCount()); // Output: 7
94+
console.log('Grid Store Count after add (Headphones match filters):', gridStore.getCount()); // Output: 4
95+
console.log('ComboBox Store Count after add (Headphones do not match "web"):', comboBoxStore.getCount()); // Output: 1
96+
97+
// Simulate changing the combobox filter
98+
comboBoxStore.filters[0].value = 'key';
99+
console.log('ComboBox Store Count (name like "key"):', comboBoxStore.getCount()); // Output: 1 (Keyboard)
100+
console.log('Grid Store Count (still unaffected):', gridStore.getCount()); // Output: 4
101+
```
102+
103+
This example demonstrates how `sourceId` enables powerful data management patterns, allowing different parts of your application to work with synchronized data while maintaining their own independent views.
104+
105+
21106
- **`observable`**: Collections are observable, meaning they can emit events when their data changes (e.g., `mutate`, `filter`, `sort`).
22107

23108
### Example: Basic Collection Usage

0 commit comments

Comments
 (0)