This guide covers common patterns and concepts used throughout the Felt SDK.
By following these patterns consistently throughout the SDK, we aim to make the API predictable and easy to use while maintaining flexibility for future enhancements.
Use of promises
All methods in the Felt SDK are asynchronous and return Promises. This means you'll need to use await or .then() when calling them:
The plural getters allow you to pass no constraints, in which case they'll return all entities of that type:
Change listeners
Each entity type has a corresponding change listener method following the pattern on{EntityType}Change:
There are also various other setters and getters in the Felt SDK that follow this convention as much as possible. For example, selection:
And layer filters:
Cleanup functions
All change listeners return an unsubscribe function that should be called when you no longer need the listener:
This is particularly important in frameworks like React where you should clean up listeners when components unmount:
Handler and options structure
Change listeners always take a single object parameter containing both options and handler. This structure makes it easier to add new options in the future without breaking existing code:
Entity nodes
When dealing with mixed collections of entities (like in selection events), each entity is wrapped in an EntityNode object that includes type information:
useEffect(() => {
const unsubscribe = felt.onViewportMove({
handler: (viewport) => {
console.log("Viewport changed:", viewport);
}
});
// Clean up when the component unmounts
return () => unsubscribe();
}, []);
// Current API
felt.onElementChange({
options: { id: "element-1" },
handler: ({ element }) => { /* ... */ }
});
// If we need to add new options later, no breaking changes:
felt.onElementChange({
options: {
id: "element-1",
newOption: "value" // Can add new options without breaking existing code
},
handler: ({ element }) => { /* ... */ }
});
felt.onSelectionChange({
handler: ({ selection }) => {
selection.forEach(node => {
console.log(node.type); // e.g., "element", "layer", "feature", ...
console.log(node.entity); // The actual entity object
if (node.type === "element") {
// TypeScript knows this is an Element
console.log(node.entity.attributes);
}
});
}
});