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
)?