1
votes

I have an OpenLayers 4 map with a single click interaction and a corresponding event handler for the "select" event that changes the selected features style.

let clickInteraction = new olInteractionSelect({
  layers: function (layer: any) {
    return layer.get('selectable') == true;
  },
  condition: olEventCondition.singleClick,
  filter: (feature: any, layer: any) => {

    let shouldReturn: boolean = false;

    switch (layer.get(this.LAYER_PROPERTY_ID)) {
      case this.LAYER_ID_POINTS:
        this.onPointClick(feature.getId());
        shouldReturn = true;
        break;
      case this.LAYER_ID_AREAS:
        this.onAreaClick(feature.getId());
        shouldReturn = true;
        break;
      default:
        break;
    }
    return shouldReturn;
  }
});

let __this = this;

clickInteraction.on('select', function (evt: any) {
  let selected = evt.selected;
  let deselected = evt.deselected;

  //Select and set style for newly selected features
  if (selected.length) {
    selected.forEach(function (feature: any) {
      if (feature.get(__this.FEATUREKEY_SELECTEDSTYLEID)) {
        feature.setStyle(__this.createStyleFnFeatureSelected(feature.get(__this.FEATUREKEY_SELECTEDSTYLEID)));
      }
    });
  } else {
    deselected.forEach(function (feature: any) {
      if (feature.get(__this.FEATUREKEY_STYLEID)) {
        feature.setStyle(__this.createStyleFn(feature.get(__this.FEATUREKEY_STYLEID)));
      }
    });
  }
});

this.map.addInteraction(clickInteraction);

Each time a new feature is selected I want to set the style of all previously selected features. What I can't figure out is when the click interaction "select" event is invoked, how do I get a collection of all the previously selected features on the map layer?

There are several thousand features on the map so iterating over all the features is not feasible from a performance perspective. What I want to achieve is to get just those features that were previously selected, not the features selected or deselected in the current click interaction event.

1
If you require 3 styles (never selected, currently selected and previously selected) you need to remove the if (selected.length) and else and process the two forEach loops unconditionally because a single event can contain both the newly select features and the any deselected by that action. If you only require separate styles for selected and not selected you can simply specify a selected style in the interaction constructor and the on select won't be needed.. - Mike
To clarify, the user would not be deselecting the features so they wouldn’t be in the deselected collection. What I want to do is deselect any previously selected features and change their style programmatically. Then apply a a style to the newly selected features. Thus, I’m trying to figure out how to get access to the collection of currently selected features at the beginning of the select event. - ChrisP

1 Answers

1
votes

You could simply maintain a queue of selected features and when new features are selected they are added to the queue. Processing of the queue can be optional, but must be done before adding the new features

let prevSelection = [];

clickInteraction.on('select', function (evt: any) {
  let selected = evt.selected;
  let deselected = evt.deselected;

  //Restyle previously selected features now if desired (or leave until next time)
  if (myCondition) {
    prevSelection.forEach(
      ...
    )
    prevSelection = [];
  }

  //Append newly selected features to queue for next time 
  prevSelection = prevSelection.concat(selected);

  //Select and set style for newly selected features
  if (selected.length) {