0

I ask a new question about the problem I have, because I tried it but I don't know how to solve it.

(I'm learning OpenLayers, and I see that it isn't that easy).

Using a html select, I run a PHP query and write a GeoJSON. What I can't do is how to dynamically load the resulting data and update the map every time the query is run. In a previous answer a user told me more or less how to do it, but I don't know how to apply it, if with ajax or that ...

In the HTML, I send by ajax the query I make:

<head>
<script type="text/javascript">
    $(document).ready(function() {
        $('form').submit(function(e){
            e.preventDefault();
            var data = '&parcel='+$('#parcel').val();
            $.ajax({
                type:"POST",
                dataType: "Json",
                url : "functionsPHP/obParcel.php",
                data:data,
                success:function(response){
                      if(response.ok){
                            datos = data.data;
        
                      }else{
                            alert('no data!');
                      }
                }
            });
            $("#formParcel")[0].reset();
        })
    })
    </script>
</head>
<body>
<form id="formParcel" name="parcelchooser" method="post" onSubmit="return false;">
<div class="col caja">
    <select id="parcel" name="parcel">
        <option value="">Select option...</option>
        <?php include "functionsPHP/parcels.php" ?>
    </select>
</div>
<input type="submit" value="OK" class="button"></input>
</form>
</body>

The PHP query:

require("db_config.php");
$conexion = "host=$db_host port=$db_port dbname=$db_name user=$db_user password=$db_pass";
$dbconn = pg_connect($conexion);
if (!$dbconn){
    echo "<center>Error DB conection!</center>";
    exit;
}
$parcel = $_POST['parcel'];
$parcel = str_replace("#",",",$parcel);

$query = "SELECT id, cadastralc, od, poligon, parcel, longitude,latitude, ST_AsGeoJSON(geom, 7) AS geojson FROM parcelsWHERE considered = 'Yes' AND id = '$parcel'";

$result = pg_query($dbconn, $query) or die('Query failed: ' . pg_last_error());

$rows = pg_num_rows($result);

// Mi variable de respuesta
$respuesta = array();

if ($rows != 0){
    $geojson = array(
        'type' => 'FeatureCollection',
        'features' => array()
    );
    $i = 0;
    while ($line = pg_fetch_assoc($result)) {
        $feature = array(
            'type' => 'Feature',
            'geometry' => json_decode($line['geojson'], true),
            'properties' => $data[]=$line,
            'id' => $i++
            );
        array_push($geojson['features'], $feature);
    }
    $observa = json_encode($geojson);
    $response["ok"] = true;
    $response["data"] = $observation;
    $response["menssage"] = "Send";
    $response["status"] = 200;
    $filename = "../data/parcels.json";
    $archivo = fopen($filename, "w");
    fwrite($file, $observation);
    fclose($file);
}else {
    $response["ok"] = false;
    $response["menssage"] = "No data";
    $response["status"] = 200;
}
echo json_encode($response);
pg_free_result($result);
pg_close($dbconn);

This is the script where I define the map and load the GeoJSON.

var styles = {
    'MultiPolygon': new ol.style.Style({
        stroke: new ol.style.Stroke({
          color: 'red',
          width: 3,
        }),
        fill: new ol.style.Fill({
          color: 'rgba(255, 255, 0, 1)',
        }),
    }),
};
var styleFunction = function (feature) {
    return styles[feature.getGeometry().getType()];
};
var osm = new ol.layer.Tile({
    title: "OSM",
    //baseLayer:true,
    source: new ol.source.OSM(),
    visible:true,
    displayInLayerSwitcher:true,
    preview: "images/logo_OSM.png"
});
//The @Eoin response
var vectorParcels = new ol.source.Vector({
    format: new  ol.format.GeoJSON(),
    loader: function(extent, resolution, projection) {
        var proj = projection.getCode();
        var xhr = new XMLHttpRequest();
        xhr.open('POST', "functionsPHP/obParcel.php");
        var onError = function() {
           vectorParcels.removeLoadedExtent(extent);
        }
        xhr.onerror = onError;
        xhr.onload = function() {
            xhr.responseText;
            if (xhr.status == 200) {
                vectorParcels.addFeatures(
                vectorParcels.getFormat().readFeatures(xhr.responseText));
                vectorParcels.refresh();
           } else {
             onError();
           }
         }
         xhr.send();
    },
});
var vectorlayer = new ol.layer.Vector({
    source:vectorParcels 
});
var view = new ol.View({
    projection: projection,
    zoom:5.6,
    center: [984934.497931, 5074393.544263]
});
var map= new ol.Map({
    target: 'map',
    view:view,
    layers: [osm, vectorlayer],
    controls: ol.control.defaults({
      zoom: false,
      attribution: false,
      rotate: false,
    }),
});
map.addControl (new ol.control.ScaleLine({
    units:'metric',
    minWidth:100
    })
);

var zoomslider = new ol.control.ZoomSlider();
//zoomslider.Target(document.getElementById('EP'));
map.addControl(zoomslider);
    
var zoomExt = new ol.control.ZoomToExtent({
extent: [-514454.2,4072762.7, 2856113.0,6173863.8],
    className:'ext'
})
mainbar.addControl(zoomExt);
var mousePosition = new ol.control.MousePosition({
    coordinateFormat: function(coordinates){
        var coord_x = coordinates[0].toFixed(3);
        var coord_y = coordinates[1].toFixed(3);
        return 'Lon: ' + coord_x + ' | ' + 'Lat: ' + coord_y;
    },
    projection: 'EPSG:3857',
    target: document.getElementById('myposition'),
    undefinedHTML: '&nbsp;'
});

map.addControl(mousePosition);

I'm POSTing the selected field, and I get the GeoJSON in the html form. The header that sends, for example is, parcel: 2 but that data should not be collected by (the @Eoin response) instead of sending it by the post I put in the form?

//The @Eoin response
var vectorParcels = new ol.source.Vector({
format: new  ol.format.GeoJSON(),
    loader: function(extent, resolution, projection) {
        var proj = projection.getCode();
        var xhr = new XMLHttpRequest();
        xhr.open('POST', "functionsPHP/obParcel.php");
        var onError = function() {
           vectorParcels.removeLoadedExtent(extent);
        }
... 
3
  • As per the Tour there should be only one question asked per question.
    – PolyGeo
    Jan 29, 2021 at 12:43
  • How and when do you run your .php query? What does it do?
    – TomazicM
    Jan 29, 2021 at 13:43
  • Just edit the question now with the ajax and the php query. I use ajax to submit the query. What I want is to update the map every time the query is run. the data is in a DB postgress and thought the best way was through a php query and write the output to a file GeoJSON.
    – user68481
    Jan 29, 2021 at 14:00

2 Answers 2

1

Firstly, you want to create a new VectorSource, like this:

var vectorSource = new Vector({
  format: new GeoJSON(),
  loader: function(extent, resolution, projection) {
     var proj = projection.getCode();
     var xhr = new XMLHttpRequest();
     xhr.open('POST', "functions/parcel.php");
     var onError = function() {
       vectorSource.removeLoadedExtent(extent);
     }
     xhr.onerror = onError;
     xhr.onload = function() {
       if (xhr.status == 200) {
         vectorSource.addFeatures(
             vectorSource.getFormat().readFeatures(xhr.responseText));
       } else {
         onError();
       }
     }
     xhr.send();
   },
 });

Secondly, make a VectorLayer from this source:

var vectorlayer = new VectorLayer({
     source:vectorSource 
})

Thirdly, add this layer to the map when it gets created:

var map = new Map({
  layers: [
    new TileLayer({
      source: new OSM(),
    }),
    vectorLayer ],
  target: 'map',
  view: new View({
    center: [0, 0],
    zoom: 2,
  }),
});

If you want to see a full working example with styling, check out this link: https://openlayers.org/en/latest/examples/vector-layer.html

Just a small side note, the geoJSON specification states that ID's don't belong inside the properties on the geoJSON.

4
  • 1
    What's missing in the above answer is method for updating the layer when desired: vectorSource.refresh();
    – TomazicM
    Jan 29, 2021 at 14:47
  • I have edited the question with the HTML part. It gives an error of the type: Uncaught SyntaxError: Unexpected token Q in JSON at position 0 at JSON.parse (<anonymous>) at Vg (JSONFeature.js: 191) at e.readFeatures (JSONFeature.js: 61) at XMLHttpRequest.xhr.onload (viewer.js: 311
    – user68481
    Jan 29, 2021 at 16:52
  • That is not a problem with openlayers, its probably related to the PHP serving up something other than a GeoJSON. Add a console.log(xhr.responseText) to the xhr.onload function and make sure that it is a valid geoJSON.
    – Eoin
    Jan 29, 2021 at 18:08
  • It doesn't receive the data that is selected in the select of the html form. How can that data be passed to the vectorSource?
    – user68481
    Feb 1, 2021 at 9:25
1

The Loader wasn't receiving the data sent by Post. So, now the page where I do the query, receives the data in json format. Also I removed the vecLayer from the Map Layer Array, and added it to the map later because the vecLayer doesn't exist. I put it all in one function, and now it works. I would have to adjust map.getView (). fit (vectorParcels.getExtent ()); because it zooms in too big for me, if the polygon thant I want to visualize is large, it doesn't grab into the map container div.

obParcel.php:

...
$params = json_decode(file_get_contents('php://input'), true);
$parcel = $params["parcel"];
...

scriptMap:

function drawParcel(parcelId){
    var vectorParcels = new ol.source.Vector({
        format: new  ol.format.GeoJSON(),
        loader: function(extent, resolution, projection) {
            var proj = projection.getCode();
            var url = "functionsPHP/obParcel.php"
            var xhr = new XMLHttpRequest();

            var params = {
                parcel: parcelId
            }

            xhr.open('POST', url);
            xhr.setRequestHeader("Content-Type", "application/json;charset=UTF-8");
            var onError = function() {
               vectorParcels.removeLoadedExtent(extent);
            }
            xhr.onerror = onError;
            xhr.onload = function() {
                xhr.responseText;
                console.log(xhr.responseText);
                if (xhr.status == 200) {
                    vectorParcels.addFeatures(
                    vectorParcels.getFormat().readFeatures(xhr.responseText));
                    map.getView().fit(vectorParcels.getExtent());
                    $("#formParcel")[0].reset();
               } else {
                 onError();
               }
             }
             xhr.send(JSON.stringify(params));
        },
    });
    var vectorlayer = new ol.layer.Vector({
        source:vectorParcels,
        visible:true,
        displayInLayerSwitcher: false,
        style: styleFunction,               
    });

    map.addLayer(vectorlayer)
}

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge that you have read and understand our privacy policy and code of conduct.

Not the answer you're looking for? Browse other questions tagged or ask your own question.