Selection & Click Interactions
Interactions in AurOpenlayers are handled declaratively within the VectorLayerDescriptor. Instead of manually managing OpenLayers event listeners and hit-testing, you define behavior contracts that the framework executes automatically.
This guide walks you through setting up click and selection interactions to make your map interactive.
Step 1: Configuring a Simple Click Interaction
To react when a user clicks a feature on a specific layer, add the click interaction to your layer descriptor.
const layerDescriptor: VectorLayerDescriptor<MapPoint, Geometry> = {
id: 'points-layer',
feature: {
id: (model) => model.id,
geometry: { /* ... */ },
style: { /* ... */ },
interactions: {
click: {
// Change the cursor when hovering over a clickable feature
cursor: 'pointer',
// Handler called when the feature is clicked
onEvent: ({ model }) => {
console.log('Clicked point:', model.name);
return true; // Return true to mark the event as handled
}
}
}
}
};
Step 2: Implementing Selection Logic
The select interaction manages the "selected" state of a feature. It can automatically apply specific styles when a feature is active.
1. Define Selection Styles
First, ensure your style configuration includes a SELECTED state.
style: {
base: (model) => ({ color: '#2563eb', radius: 10 }),
states: {
SELECTED: () => ({ color: '#f97316', radius: 14 }), // Orange and larger when selected
},
render: (opts) => new Style({ /* ... uses opts.color and opts.radius */ })
}
2. Enable the Select Interaction
Add the select configuration to your interactions block.
interactions: {
select: {
state: 'SELECTED', // Framework applies this state automatically
cursor: 'pointer',
onEvent: ({ model }) => {
this.selectedPoint = model; // Sync with your Angular component
return true;
}
}
}
Step 3: Controlling Event Propagation
When multiple features from different layers overlap, you need to decide if a click should "pierce through" to lower layers. Use the propagation property:
stop(Default): The event stops at this layer if a feature is hit.continue: The event is passed to layers below even if a feature on this layer is hit.auto: Behavior is determined by the result of theonEventhandler.
interactions: {
click: {
propagation: 'stop',
onEvent: () => true
}
}
Step 4: Advanced Selection with pickTarget
If multiple features are under the cursor (e.g., a point and a line), use pickTarget to provide custom logic for which feature should actually be selected.
In this example, we only allow selecting the point that is currently in "edit mode" in our application:
interactions: {
select: {
pickTarget: ({ candidates }) => {
// 'candidates' is an array of { model, feature } under the click
return candidates.find(c => c.model.id === this.editingPointId);
},
onEvent: ({ model }) => {
this.startEditing(model.id);
return true;
}
}
}
Step 5: Toggling Interactions Dynamically
You can enable or disable interactions at runtime using the enabled property, which accepts a boolean or a function.
readonly mapConfig: MapHostConfig = {
schema: {
layers: [
{
id: 'interactive-layer',
feature: {
// ...
interactions: {
select: {
// Disables selection based on component state
enabled: () => this.isSelectToolActive,
state: 'SELECTED'
}
}
}
}
]
}
};
Summary of Interaction Properties
| Property | Type | Description |
| :--- | :--- | :--- |
| enabled | boolean \| (() => boolean) | Whether the interaction is active. |
| cursor | string | CSS cursor (e.g., 'pointer', 'grab') shown when hovering over the feature. |
| state | FeatureState | The style state(s) to apply when the interaction is active (e.g., 'SELECTED'). |
| propagation | 'stop' \| 'continue' \| 'auto' | Determines if the event bubbles down to other layers. |
| onEvent | Function | Callback triggered by the interaction (click, select, etc.). |
| pickTarget | Function | Filters/Selects the specific feature when multiple candidates are hit. |