Skip to main content
Notice removed Authoritative reference needed by CommunityBot
Bounty Ended with no winning answer by CommunityBot
Tweeted twitter.com/StackGIS/status/766308190380232704
Notice added Authoritative reference needed by Lars
Bounty Started worth 50 reputation by Lars
Some more information about what was tried so far
Source Link
Lars
  • 2.2k
  • 2
  • 19
  • 33
// DEFAULT variables
var defaultCenter = [-2.15, 52.267];
var defaultZoom = 12;
var epsgWGS84 = 'EPSG:4326';
var epsgDefaultMapOL = 'EPSG:3857';
var defaultTarget = 'map';

// Constructor
function MapManager(target, center, zoom){
    // check if parameters are set - use defaults otherwise
    if(!target){
        target = defaultTarget;
    }
    if(!center){
        center = defaultCenter;
    }
    if(!zoom){
        zoom = defaultZoom;
    }
    this.map = this.initMap(target, center, zoom);
    this.selectedFeatureselectedFeatureProperties = null;{prop1: "initialValue"};
}


// Getter for feature properties
MapManager.prototype.getSelectedFeaturegetSelectedFeatureProperties = function(){
    return this.selectedFeature;selectedFeatureProperties;
};

// get feature properties fromSetter selectedfor feature (filtered properties - e.g. no geometry)
MapManager.prototype.getSelectedFeaturePropertiessetSelectedFeatureProperties = function(feature){
    //var displayPropertiesthis_ = [];this;
    console.log("setting selected feature properties...");
    var displayProperties = {};
    if(this.getSelectedFeature()feature != null){
        $.each(this.getSelectedFeature()feature.getProperties(), function(key, value) {
            // skip the geometry property
            if(key != "geometry"){
                displayProperties[key] = value;
            }
        });
    }
    return displayProperties;
}

// Setter
MapManager.prototypeconsole.setSelectedFeature = functionlog(featuredisplayProperties){;
    this.selectedFeatureselectedFeatureProperties = feature;displayProperties;
};

// Geojsonsome geojson with lines
var geojsonObject = {
    'type': 'FeatureCollection',
    'crs': {
        'type': 'name',
        'properties': {
            'name': 'EPSG:4326'
        }
    },
    'features': [
        {
            'type': 'Feature',
            'properties': {
                'prop1': 'feature1',
                'prop2': 'Blub'
            },
            'geometry': {
                'type': 'LineString',
                'coordinates': [
                    [-2.176, 52.266], [-2.166, 52.276]
                ]
            }
        },
        {
            'type': 'Feature',
            'properties': {
                'prop1': 'feature2',
                'prop2': 'Test'
            },
            'geometry': {
                'type': 'LineString',
                'coordinates': [
                    [-2.132, 52.272], [-2.145, 52.258]
                ]
            }
        }
    ]
};

// create vector source with geojson
var vectorSource = new ol.source.Vector({
    features: (new ol.format.GeoJSON()).readFeatures(geojsonObject, {
        dataProjection: 'EPSG:4326',
        featureProjection: 'EPSG:3857'
    })
});


// ### Create layers
// create osm layer
function createLayerWebOSM(){
    return new ol.layer.Tile({
        source: new ol.source.OSM(),
        projection: epsgDefaultMapOL
    });
}

// create vector layer (using geojson vector source)
var vectorLayer = new ol.layer.Vector({
    source: vectorSource
});


// Initialize map
MapManager.prototype.initMap = function(target, center, zoom){
    var this_ = this;
    var map = new ol.Map({
        target: target,
        layers: [createLayerWebOSM(), vectorLayer],
        view: new ol.View({
        center: ol.proj.transform(center, epsgWGS84, epsgDefaultMapOL),
        zoom: zoom
      })
    });
    
    // make vector layer selectable
    vectorLayer.set('selectable', true);
    
    map.addInteraction(new ol.interaction.Select({
        layers: function(layer) {
            return layer.get("selectable") == true;
        }
    }));
    
    
    // add click interaction
    map.on("click", function(e) {
        map.forEachFeatureAtPixel(e.pixel, function (feature, layer) {
            console.log("new feature selected -> ");
            console.log(feature);
            this_.setSelectedFeaturesetSelectedFeatureProperties(feature);
            console.log("new feature properties -> ");
            console.log(this_.getSelectedFeatureProperties());
        });
    });
    return map;
}
var app = angular.module('myApp', []);

// Controller
app.controller('appController', function($scope, $q){
    $scope.mapManager = new MapManager();
    $scope.selectedFeatureProperties = {};
    
    // watch if the selected feature changes
    $scope.$watch(function($scope) {
        //return $scope.mapManager.getSelectedFeatureProperties();
        //return $scope.mapManager.getSelectedFeature();
    },
    function(newFeature, oldFeature, $scope) {
        console.log("change detected...");
        $scope.selectedFeatureProperties = $scope.mapManager.getSelectedFeatureProperties();
    }, true);
    
});

You can see the essential part of the code at this JSFiddleJSFiddle. Some logs indicate that the selectedFeature variable is actually changing...

EDIT: In the MapManager I am now saving the feature properties (selectedFeatureProperties) directly and not the ol.Feature itself. I tried $watch and $watchCollection with and without true/false as last parameter but the listener is not called when the selectedFeatureProperties are changing... If I am understanding the third parameter correctly in my case it should not matter if it is true or false because the reference of the selectedFeatureProperties and the values of the properties are both changing? Moreover I tried to pass the watchExpression as String

"mapManager.getSelectedFeatureProperties()"

or as a function

function(){
  return $scope.mapManager.getSelectedFeatureProperties();
},

but that did not change anything. I adjusted the JSFiddle with some comments so you can see what I tried...

// DEFAULT variables
var defaultCenter = [-2.15, 52.267];
var defaultZoom = 12;
var epsgWGS84 = 'EPSG:4326';
var epsgDefaultMapOL = 'EPSG:3857';
var defaultTarget = 'map';

// Constructor
function MapManager(target, center, zoom){
    // check if parameters are set - use defaults otherwise
    if(!target){
        target = defaultTarget;
    }
    if(!center){
        center = defaultCenter;
    }
    if(!zoom){
        zoom = defaultZoom;
    }
    this.map = this.initMap(target, center, zoom);
    this.selectedFeature = null;
}


// Getter
MapManager.prototype.getSelectedFeature = function(){
    return this.selectedFeature;
};

// get feature properties from selected feature (filtered properties - e.g. no geometry)
MapManager.prototype.getSelectedFeatureProperties = function(){
    //var displayProperties = [];
    var displayProperties = {};
    if(this.getSelectedFeature() != null){
        $.each(this.getSelectedFeature().getProperties(), function(key, value) {
            // skip the geometry property
            if(key != "geometry"){
                displayProperties[key] = value;
            }
        });
    }
    return displayProperties;
}

// Setter
MapManager.prototype.setSelectedFeature = function(feature){
    this.selectedFeature = feature;
};

// Geojson with lines
var geojsonObject = {
    'type': 'FeatureCollection',
    'crs': {
        'type': 'name',
        'properties': {
            'name': 'EPSG:4326'
        }
    },
    'features': [
        {
            'type': 'Feature',
            'properties': {
                'prop1': 'feature1',
                'prop2': 'Blub'
            },
            'geometry': {
                'type': 'LineString',
                'coordinates': [
                    [-2.176, 52.266], [-2.166, 52.276]
                ]
            }
        },
        {
            'type': 'Feature',
            'properties': {
                'prop1': 'feature2',
                'prop2': 'Test'
            },
            'geometry': {
                'type': 'LineString',
                'coordinates': [
                    [-2.132, 52.272], [-2.145, 52.258]
                ]
            }
        }
    ]
};

// create vector source with geojson
var vectorSource = new ol.source.Vector({
    features: (new ol.format.GeoJSON()).readFeatures(geojsonObject, {
        dataProjection: 'EPSG:4326',
        featureProjection: 'EPSG:3857'
    })
});


// ### Create layers
// create osm layer
function createLayerWebOSM(){
    return new ol.layer.Tile({
        source: new ol.source.OSM(),
        projection: epsgDefaultMapOL
    });
}

// create vector layer (using geojson vector source)
var vectorLayer = new ol.layer.Vector({
    source: vectorSource
});


// Initialize map
MapManager.prototype.initMap = function(target, center, zoom){
    this_ = this;
    var map = new ol.Map({
        target: target,
        layers: [createLayerWebOSM(), vectorLayer],
        view: new ol.View({
        center: ol.proj.transform(center, epsgWGS84, epsgDefaultMapOL),
        zoom: zoom
      })
    });
    
    // make vector layer selectable
    vectorLayer.set('selectable', true);
    
    map.addInteraction(new ol.interaction.Select({
        layers: function(layer) {
            return layer.get("selectable") == true;
        }
    }));
    
    
    // add click interaction
    map.on("click", function(e) {
        map.forEachFeatureAtPixel(e.pixel, function (feature, layer) {
            this_.setSelectedFeature(feature);
        });
    });
    return map;
}
var app = angular.module('myApp', []);

// Controller
app.controller('appController', function($scope, $q){
    $scope.mapManager = new MapManager();
    $scope.selectedFeatureProperties = {};
    
    // watch if the selected feature changes
    $scope.$watch(function($scope) {
        //return $scope.mapManager.getSelectedFeatureProperties();
        return $scope.mapManager.getSelectedFeature();
    },
    function(newFeature, oldFeature, $scope) {
        console.log("change detected...");
        $scope.selectedFeatureProperties = $scope.mapManager.getSelectedFeatureProperties();
    }, true);
    
});

You can see the essential part of the code at this JSFiddle. Some logs indicate that the selectedFeature variable is actually changing...

// DEFAULT variables
var defaultCenter = [-2.15, 52.267];
var defaultZoom = 12;
var epsgWGS84 = 'EPSG:4326';
var epsgDefaultMapOL = 'EPSG:3857';
var defaultTarget = 'map';

// Constructor
function MapManager(target, center, zoom){
    // check if parameters are set - use defaults otherwise
    if(!target){
        target = defaultTarget;
    }
    if(!center){
        center = defaultCenter;
    }
    if(!zoom){
        zoom = defaultZoom;
    }
    this.map = this.initMap(target, center, zoom);
    this.selectedFeatureProperties = {prop1: "initialValue"};
}


// Getter for feature properties
MapManager.prototype.getSelectedFeatureProperties = function(){
    return this.selectedFeatureProperties;
};

// Setter for feature properties
MapManager.prototype.setSelectedFeatureProperties = function(feature){
    var this_ = this;
    console.log("setting selected feature properties...");
    var displayProperties = {};
    if(feature != null){
        $.each(feature.getProperties(), function(key, value) {
            // skip the geometry property
            if(key != "geometry"){
                displayProperties[key] = value;
            }
        });
    }
    console.log(displayProperties);
    this.selectedFeatureProperties = displayProperties;
}

// some geojson with lines
var geojsonObject = {
    'type': 'FeatureCollection',
    'crs': {
        'type': 'name',
        'properties': {
            'name': 'EPSG:4326'
        }
    },
    'features': [
        {
            'type': 'Feature',
            'properties': {
                'prop1': 'feature1',
                'prop2': 'Blub'
            },
            'geometry': {
                'type': 'LineString',
                'coordinates': [
                    [-2.176, 52.266], [-2.166, 52.276]
                ]
            }
        },
        {
            'type': 'Feature',
            'properties': {
                'prop1': 'feature2',
                'prop2': 'Test'
            },
            'geometry': {
                'type': 'LineString',
                'coordinates': [
                    [-2.132, 52.272], [-2.145, 52.258]
                ]
            }
        }
    ]
};

// create vector source with geojson
var vectorSource = new ol.source.Vector({
    features: (new ol.format.GeoJSON()).readFeatures(geojsonObject, {
        dataProjection: 'EPSG:4326',
        featureProjection: 'EPSG:3857'
    })
});


// ### Create layers
// create osm layer
function createLayerWebOSM(){
    return new ol.layer.Tile({
        source: new ol.source.OSM(),
        projection: epsgDefaultMapOL
    });
}

// create vector layer (using geojson vector source)
var vectorLayer = new ol.layer.Vector({
    source: vectorSource
});


// Initialize map
MapManager.prototype.initMap = function(target, center, zoom){
    var this_ = this;
    var map = new ol.Map({
        target: target,
        layers: [createLayerWebOSM(), vectorLayer],
        view: new ol.View({
        center: ol.proj.transform(center, epsgWGS84, epsgDefaultMapOL),
        zoom: zoom
      })
    });
    
    // make vector layer selectable
    vectorLayer.set('selectable', true);
    
    map.addInteraction(new ol.interaction.Select({
        layers: function(layer) {
            return layer.get("selectable") == true;
        }
    }));
    
    
    // add click interaction
    map.on("click", function(e) {
        map.forEachFeatureAtPixel(e.pixel, function (feature, layer) {
            console.log("new feature selected -> ");
            console.log(feature);
            this_.setSelectedFeatureProperties(feature);
            console.log("new feature properties -> ");
            console.log(this_.getSelectedFeatureProperties());
        });
    });
    return map;
}
var app = angular.module('myApp', []);

// Controller
app.controller('appController', function($scope, $q){
    $scope.mapManager = new MapManager();
    $scope.selectedFeatureProperties = {};
    
    // watch if the selected feature changes
    $scope.$watch(function() {
        return $scope.mapManager.getSelectedFeatureProperties();
        //return $scope.mapManager.getSelectedFeature();
    },
    function(newFeature, oldFeature) {
        console.log("change detected...");
        $scope.selectedFeatureProperties = $scope.mapManager.getSelectedFeatureProperties();
    }, true);
    
});

You can see the essential part of the code at this JSFiddle. Some logs indicate that the selectedFeature variable is actually changing...

EDIT: In the MapManager I am now saving the feature properties (selectedFeatureProperties) directly and not the ol.Feature itself. I tried $watch and $watchCollection with and without true/false as last parameter but the listener is not called when the selectedFeatureProperties are changing... If I am understanding the third parameter correctly in my case it should not matter if it is true or false because the reference of the selectedFeatureProperties and the values of the properties are both changing? Moreover I tried to pass the watchExpression as String

"mapManager.getSelectedFeatureProperties()"

or as a function

function(){
  return $scope.mapManager.getSelectedFeatureProperties();
},

but that did not change anything. I adjusted the JSFiddle with some comments so you can see what I tried...

changed fiddlejs link
Source Link
Lars
  • 2.2k
  • 2
  • 19
  • 33

How to get selected OL3 feature properties with Angular JSAngularJS ($scope.$watch)

You can see the essential part of the code at this JSFiddleJSFiddle. Some logs indicate that the selectedFeature variable is actually changing...

How to get selected OL3 feature properties with Angular JS ($scope.$watch)

You can see the essential part of the code at this JSFiddle. Some logs indicate that the selectedFeature variable is actually changing...

How to get selected OL3 feature properties with AngularJS ($scope.$watch)

You can see the essential part of the code at this JSFiddle. Some logs indicate that the selectedFeature variable is actually changing...

Source Link
Lars
  • 2.2k
  • 2
  • 19
  • 33

How to get selected OL3 feature properties with Angular JS ($scope.$watch)

I want to display feature properties that have been selected in an OpenLayers3 map. I am using AngularJS and try to update the currently selected feature properties using $scope$watch.

I have a MapManager file that is used to handle all necessary OL3 operations:

// DEFAULT variables
var defaultCenter = [-2.15, 52.267];
var defaultZoom = 12;
var epsgWGS84 = 'EPSG:4326';
var epsgDefaultMapOL = 'EPSG:3857';
var defaultTarget = 'map';

// Constructor
function MapManager(target, center, zoom){
    // check if parameters are set - use defaults otherwise
    if(!target){
        target = defaultTarget;
    }
    if(!center){
        center = defaultCenter;
    }
    if(!zoom){
        zoom = defaultZoom;
    }
    this.map = this.initMap(target, center, zoom);
    this.selectedFeature = null;
}


// Getter
MapManager.prototype.getSelectedFeature = function(){
    return this.selectedFeature;
};

// get feature properties from selected feature (filtered properties - e.g. no geometry)
MapManager.prototype.getSelectedFeatureProperties = function(){
    //var displayProperties = [];
    var displayProperties = {};
    if(this.getSelectedFeature() != null){
        $.each(this.getSelectedFeature().getProperties(), function(key, value) {
            // skip the geometry property
            if(key != "geometry"){
                displayProperties[key] = value;
            }
        });
    }
    return displayProperties;
}

// Setter
MapManager.prototype.setSelectedFeature = function(feature){
    this.selectedFeature = feature;
};

// Geojson with lines
var geojsonObject = {
    'type': 'FeatureCollection',
    'crs': {
        'type': 'name',
        'properties': {
            'name': 'EPSG:4326'
        }
    },
    'features': [
        {
            'type': 'Feature',
            'properties': {
                'prop1': 'feature1',
                'prop2': 'Blub'
            },
            'geometry': {
                'type': 'LineString',
                'coordinates': [
                    [-2.176, 52.266], [-2.166, 52.276]
                ]
            }
        },
        {
            'type': 'Feature',
            'properties': {
                'prop1': 'feature2',
                'prop2': 'Test'
            },
            'geometry': {
                'type': 'LineString',
                'coordinates': [
                    [-2.132, 52.272], [-2.145, 52.258]
                ]
            }
        }
    ]
};

// create vector source with geojson
var vectorSource = new ol.source.Vector({
    features: (new ol.format.GeoJSON()).readFeatures(geojsonObject, {
        dataProjection: 'EPSG:4326',
        featureProjection: 'EPSG:3857'
    })
});


// ### Create layers
// create osm layer
function createLayerWebOSM(){
    return new ol.layer.Tile({
        source: new ol.source.OSM(),
        projection: epsgDefaultMapOL
    });
}

// create vector layer (using geojson vector source)
var vectorLayer = new ol.layer.Vector({
    source: vectorSource
});


// Initialize map
MapManager.prototype.initMap = function(target, center, zoom){
    this_ = this;
    var map = new ol.Map({
        target: target,
        layers: [createLayerWebOSM(), vectorLayer],
        view: new ol.View({
        center: ol.proj.transform(center, epsgWGS84, epsgDefaultMapOL),
        zoom: zoom
      })
    });
    
    // make vector layer selectable
    vectorLayer.set('selectable', true);
    
    map.addInteraction(new ol.interaction.Select({
        layers: function(layer) {
            return layer.get("selectable") == true;
        }
    }));
    
    
    // add click interaction
    map.on("click", function(e) {
        map.forEachFeatureAtPixel(e.pixel, function (feature, layer) {
            this_.setSelectedFeature(feature);
        });
    });
    return map;
}

When a feature is clicked on the map it is stored and can be accessed with an according getter which is watched in the Angular controller:

var app = angular.module('myApp', []);

// Controller
app.controller('appController', function($scope, $q){
    $scope.mapManager = new MapManager();
    $scope.selectedFeatureProperties = {};
    
    // watch if the selected feature changes
    $scope.$watch(function($scope) {
        //return $scope.mapManager.getSelectedFeatureProperties();
        return $scope.mapManager.getSelectedFeature();
    },
    function(newFeature, oldFeature, $scope) {
        console.log("change detected...");
        $scope.selectedFeatureProperties = $scope.mapManager.getSelectedFeatureProperties();
    }, true);
    
});

I want to display the properties of the currently selected feature in a table:

<div id="main" data-ng-controller="appController">
    <!-- table with selected feature inforamtion -->
    <h4> Selected Feature Properties </h4>
    <table>
        <tr>
            <th> Property </th>
            <th> Value </th>
        </tr>
        <tr ng-repeat="(property, value) in selectedFeatureProperties">
            <td>{{ property }}</td>
            <td>{{ value }}</td>
        </tr>
    </table>
        
    <div id='map'></div>
</div>

It seems that the change is ignored.

You can see the essential part of the code at this JSFiddle. Some logs indicate that the selectedFeature variable is actually changing...

What am I doing wrong? Is there an easier way to do this (instead of using $scope$watch)?