G
GJB author
I'm using PHPRunner v10.91 (Build 41974 x64), PostGIS v12.10, and Firefox v127.0 as browser. NOTE: This code would be better suited to be in a "Validate As" function, but since I'm using a Text Area (not a Text Field), that's not an option in v10, apparently. Then the error would focus the screen to the bad field, and highlight the field Title, box, and error message in red. That's a whole other issue. Problem solved:- I have a Geometry field in PostGIS (called "geom")
- I want to List and Edit it as a GeoJSON text ("geom_json"), but update it back to the "geom" field.
- NOTE: GeoJSON can contain invalid geometries, so I must validate both:
- the GeoJSON format, and
- the geometry
I'm providing two similar but slightly different solutions to this problem - In the Save button code.
- In a Field Event ("Change") for the Text Area input box.
There's lots of debugging text still here that can be cleaned up. Hope this is clear enough, and useful to someone else! Notes / Setup:- DB: I have a Geometry field in PostGIS (called "geom")
- Query tab: setup following rows in Query designer tab ("Output" checked for both):
- Fields tab:
- geom field is unchecked
- geom_json field is checked
- and "List" and "Edit" columns are checked (at least)
- Set Properties for geom_json ("..." button)
- "Edit as" tab:
- Select "Text area"
- Check "Insert NULL values instead of empty strings"
- Set your box "Height"
- Designer tab --> Edit page:
Save button codeNOTE: in this function: - Only if there's an error, then $message is printed as the error message
- The Save button error message appears at the top of the page.
- Click on Save button to validate data and see error messages.
- To validate and see error messages: change the data, and click on Save button.
Interesting functions from below: In the Events tab --> Edit page --> Before record updated - After the following code:
if ($values['geom_json'] == '') { $values['geom_json'] = NULL; }
- Added the following:
// Validate GeoJSON value. Then validate Geometry. If all OK, then update. // NOTE: for debugging, "return false;" to see $message in last case
// Validate GeoJSON value here. $sql = "SELECT ST_AsText(ST_GeomFromGeoJSON('" . $values['geom_json'] . "')) As wkt"; $message = "Save Button: \"Before record update\" (BeforeEdit) message:
Test GeoJSON SQL: " . $sql; $result = DB::Exec($sql); if (!$result) { // GeoJSON validation failed $message .= "
Invalid GeoJSON!"; $errormsg = DB::LastError(); $message .= "
GeoJSON string: " . $values['geom_json'] . "
SQL error message: " . $errormsg; return false; } else { // GeoJSON valid, now test Geometry $message .= "
Valid GeoJSON!";
// Validate Geometry here. $sql = "SELECT valid, reason, ST_AsText(location) AS location from ST_IsValidDetail (ST_GeomFromGeoJSON('" . $values['geom_json'] . "'))"; $message .= "
Test Geometry SQL: " . $sql; $rs = DB::Query($sql); $data = $rs->fetchAssoc();
if ($data["valid"] == "f") { // If Geometry invalid, then Error $message .= "
Invalid Geometry."; // $message .= " Validity: " . $data["valid"]; $message .= " Reason: " . $data["reason"]; // Sometimes "location" is empty in error, so don't display it if not needed. if ($data["location"] != "") { $message .= " Location: " . $data["location"]; } return false; } else { // Else if Geometry Valid, then update. // Update geom with geom_json data (force polygon coordinates to be counter-clock wise, CCW), $sqlValues['geom'] = 'ST_ForcePolygonCCW (ST_GeomFromGeoJSON(\''.$values['geom_json'].'\'))'; // remove geom_json from record update unset($values['geom_json']); } }
return true; One screenshot (Test data set #3):
Field Event ("Change") codeNote: - The field event error message appears just below the Tooltip for the geom_json field.
- Debugging messages (console.debug) appear in the Browser Console window as "Debug" messages.
- Some of the code below is redundant, and appears just to make it as similar as possible to the code above.
- To validate and see error messages: change the data, and click outside the text area box.
To display error messages below the geom_json field text area box, add the following: - Designer tab --> Edit page:
- Just below Tooltip for "geom_json" field, Inserted following HTML Text:
<div id='geom_error_message' /></div>
- Added following CSS to make message same colour as other error messages (not quite red):
- Select this new HTML Text button --> click "Custom CSS" button:
#geom_error_message { color: #b94a48; font-weight: bold; }
Added the Change field event: - Designer tab --> Edit page --> Select "geom_json" field --> Click "View as/Edit as" button:
- "Edit as" tab, click "Field events" button
- Add a "new handler" called "geom_json_event" for event "Change"
- Note: Once you've created the field event, you may find the code on the Events tab --> Field events... --> geom_json_event
Added (Modified) the code: // Get GeoJSON text string params["geom_json"] = this.getValue(); // ajax.setMessage("Sending request to server..."); // ajax.setMessage doesn't work here console.debug ("In Field Event: geom_json_event (Client Before). Edited field: " + params["geom_json"]); $result["txt"] = ""; $values["geom_json"] = $params["geom_json"];
// Validate GeoJSON value. Then validate Geometry.
// Validate GeoJSON value here. $sql = "SELECT ST_AsText(ST_GeomFromGeoJSON('" . $values['geom_json'] . "')) As wkt"; // $message = "TESTING - Field Event: OnServer message SQL: " . $sql . "
"; $rs = DB::Exec($sql); if (!$rs) { // GeoJSON validation failed $message .= "Invalid GeoJSON!"; $errormsg = DB::LastError(); // $message .= " GeoJSON string: " . $values['geom_json']; $message .= "
SQL error message: " . $errormsg; $result['validity'] = false; // return false; } else { // GeoJSON valid, now test Geometry $message .= "Valid GeoJSON";
// Validate Geometry here. $sql = "SELECT valid, reason, ST_AsText(location) AS location from ST_IsValidDetail (ST_GeomFromGeoJSON('" . $values['geom_json'] . "'))"; // $message .= "
Geometry SQL: " . $sql; $rs = DB::Query($sql); $data = $rs->fetchAssoc();
if ($data["valid"] == "f") { // If Geometry invalid, then Error $message .= ", but Invalid Geometry!"; // $message .= " Validity: " . $data["valid"]; $message .= "
Reason: " . $data["reason"]; // Sometimes "location" in error is empty, so don't display it if not needed. if ($data["location"] != "") { $message .= " Location: " . $data["location"]; } $result['validity'] = false; // return false; } else { // Else if Geometry Valid, then pass validity test. $message .= "."; $result['validity'] = true; } } $result["txt"] .= $message; // Display message var message = "In Field Event: geom_json_event (Client After).
" + result["txt"]; if (result["validity"]) { // Valid $("#geom_error_message").html(""); } else { // Invalid $("#geom_error_message").html(message); } // ajax.setMessage(message); // DOESN'T work console.debug (message); One screenshot (Test data set #2):
Test Data:- Good:
- (1) Valid GeoJSON, Valid Geometry
- {"type":"Polygon","coordinates":[[[-129.07157621,64.005109936],[-129.07157621,70.001972143],[-124.865609743,70.001972143],[-124.865609743,64.005109936],[-129.07157621,64.005109936]]]}
- Bad:
- (2) INVALID GeoJSON:
- {"typePolygon","coordinates":[[[-129.07157621,64.005109936],[-129.07157621,70.001972143],[-124.865609743,70.001972143],[-124.865609743,64.005109936],[-129.07157621,64.005109936]]]}
- Valid GeoJSON:
- (3) INVALID Geometry - Last coordinate not same as first. No "Location":
- {"type":"Polygon","coordinates":[[[101.0,64.005109936],[-129.07157621,70.001972143],[-124.865609743,70.001972143],[-124.865609743,64.005109936],[-129.07157621,64.005109936]]]}
- (4) INVALID Geometry - Self-intersection. Location=intersection point:
- {"type":"Polygon","coordinates":[[[20,20],[120,190],[50,190],[170,50],[20,20]]]}
|
|