How to use openlayers getUrl function in new ImageWMS? - reactjs

I am using OpenLayers in my reactjs project. As per the documentation
I have tried the following code
var sourceData = new ImageWMS(
{
params: {'LAYERS': 'top:states'},
ratio: 1,
serverType: 'geoserver',
getURL: function () {
console.log('bounds');
}
});
this.olmap = new Map({
target: null,
layers: [new ImageLayer({
extent: [-13884991, 2870341, -7455066, 6338219],
source: sourceData
})],
view: new View({
center: this.state.center,
zoom: this.state.zoom
})
});
I am trying the above code but it is not showing console log.
Can I know how to make it work so that I can get the console log?

It simply returns the url used to construct the source, e.g.
var sourceData = new ImageWMS(
{
url: 'https://ahocevar.com/geoserver/wms',
params: {'LAYERS': 'top:states'},
ratio: 1,
serverType: 'geoserver'
});
console.log(sourceData.getURL()); // 'https://ahocevar.com/geoserver/wms'
To log the full url or its query string parameters you would need to customise the imageLoadFunction
var sourceData = new ImageWMS(
{
url: 'https://ahocevar.com/geoserver/wms',
params: {'LAYERS': 'top:states'},
ratio: 1,
serverType: 'geoserver',
imageLoadFunction: function(image, src) {
var params = new URLSearchParams(src.slice(src.indexOf('?')));
console.log('bounds', params.get('BBOX'));
image.getImage().src = src;
}
});

Related

How to prevent the suggestedResult from collapsing after clicking result using SearchWidget?

How to prevent the suggestedResult from collapsing after clicking result using SearchWidget?
CodePen, copied below
// An open data address search API for France
const url = "https://api-adresse.data.gouv.fr/";
const map = new Map({
basemap: "streets-vector"
});
const view = new MapView({
container: "viewDiv",
map: map,
center: [2.21, 46.22], // lon, lat
scale: 3000000
});
const customSearchSource = new SearchSource({
placeholder: "example: 8 Boulevard du Port",
// Provide a getSuggestions method
// to provide suggestions to the Search widget
getSuggestions: (params) => {
// You can request data from a
// third-party source to find some
// suggestions with provided suggestTerm
// the user types in the Search widget
return esriRequest(url + "search/", {
query: {
q: params.suggestTerm.replace(/ /g, "+"),
limit: 6,
lat: view.center.latitude,
lon: view.center.longitude
},
responseType: "json"
}).then((results) => {
// Return Suggestion results to display
// in the Search widget
return results.data.features.map((feature) => {
return {
key: "name",
text: feature.properties.label,
sourceIndex: params.sourceIndex
};
});
});
},
// Provide a getResults method to find
// results from the suggestions
getResults: (params) => {
// If the Search widget passes the current location,
// you can use this in your own custom source
const operation = params.location ? "reverse/" : "search/";
let query = {};
// You can perform a different query if a location
// is provided
if (params.location) {
query.lat = params.location.latitude;
query.lon = params.location.longitude;
} else {
query.q = params.suggestResult.text.replace(/ /g, "+");
query.limit = 6;
}
return esriRequest(url + operation, {
query: query,
responseType: "json"
}).then((results) => {
// Parse the results of your custom search
const searchResults = results.data.features.map((feature) => {
// Create a Graphic the Search widget can display
const graphic = new Graphic({
geometry: new Point({
x: feature.geometry.coordinates[0],
y: feature.geometry.coordinates[1]
}),
attributes: feature.properties
});
// Optionally, you can provide an extent for
// a point result, so the view can zoom to it
const buffer = geometryEngine.geodesicBuffer(
graphic.geometry,
100,
"meters"
);
// Return a Search Result
const searchResult = {
extent: buffer.extent,
feature: graphic,
name: feature.properties.label
};
return searchResult;
});
// Return an array of Search Results
return searchResults;
});
}
});
// Create Search widget using custom SearchSource
const searchWidget = new Search({
view: view,
sources: [customSearchSource],
includeDefaultSources: false
});
// Add the search widget to the top left corner of the view
view.ui.add(searchWidget, {
position: "top-right"
});
3d version of code sample above
There is no documented way to do this through the API, as far as I can tell. But by adding the esri-search--show-suggestions to the SearchWidget, the suggestions will reappear:
const searchWidget = new Search({
view: view,
sources: [customSearchSource],
includeDefaultSources: false,
//autoSelect: false,
goToOverride: function(view, { target, options }) {
view.goTo(target, options);
const widget = document.querySelector('.esri-search__container')
widget.className += ' esri-search--show-suggestions'
},
});
Working CodePen here

How to use Angular Js ajax with dx-scheduler

I am using dx-scheduler calendar and i'm trying to use crud operations for the meetings. I wonder how can i use functions in DevExpress.data.AspNet.createStore instead of their own api methods - here is an example of their API :
DevExpress.data.AspNet.createStore({
key: "AppointmentId",
loadUrl: url + "/Get",
insertUrl: url + "/Post",
updateUrl: url + "/Put",
deleteUrl: url + "/Delete",
onBeforeSend: function(method, ajaxOptions) {
ajaxOptions.xhrFields = { withCredentials: true };
}
}),
I want to achieve this :
DevExpress.data.AspNet.createStore({
key: "AppointmentId",
loadUrl: function(){
$http.get("/getApi").then(function(){
// manipulate the fetched data
})
},
insertUrl: : function(values){
// manipulate the values before post
$http.post("/getApi", values).then(function(){
}),
onBeforeSend: function(method, ajaxOptions) {
ajaxOptions.xhrFields = { withCredentials: true };
}
}),
Example.
According to Documentation in this link
loadUrl - the URL used to load data. I assume that you should pass the URL string here for your get api.
if parameters is needed for your get request you can send them using LoadParams Option
loadParams - additional parameters that should be passed to loadUrl.
and handle the result by implementing the onLoaded ..
onLoaded - refer to CustomStore.onLoaded.
$scope.schedulerOptions = {
dataSource: DevExpress.data.AspNet.createStore({
key: "AppointmentId",
// loadUrl: 'https://jsonplaceholder.typicode.com/posts',
loadUrl: "https://jsonplaceholder.typicode.com/posts",
insertUrl: url + "/Post",
updateUrl: url + "/Put",
deleteUrl: url + "/Delete",
onBeforeSend: function(method, ajaxOptions) {
ajaxOptions.xhrFields = { withCredentials: true };
},
onLoaded:function(result){
console.log(result)
var data = result;
for (var i in data) {
data[i].StartDate = '2020-12-20T10:00:00Z';
data[i].EndDate = '2020-12-20T11:00:00Z';
}
return data;
}
}),
// remoteFiltering: true,
dateSerializationFormat: "yyyy-MM-ddTHH:mm:ssZ",
views: ["day", "workWeek", "month"],
currentView: "day",
currentDate: new Date(),
startDayHour: 9,
endDayHour: 19,
height: 600,
textExpr: "title",
startDateExpr: "StartDate",
endDateExpr: "EndDate",
allDayExpr: "AllDay"
};
The result from the get request is printed in the console in the onLoaded function
The data you are using in your example in this json
https://jsonplaceholder.typicode.com/posts
Does not contain EndDate , maybe if you modified it to include Start Date and EndDate with the same dateSerializationFormat it will work, I modified them manually and it worked, I also modified textExpr to display title.
your Example link modified
In order to use your own Ajax request , you can use the following work around, Initialize the schedulerOptions after you do your Ajax call using the result as data resource. Example link
Html :
<div class="dx-viewport demo-container" ng-app="DemoApp" ng-controller="DemoController">
<div dx-scheduler="schedulerOptions" ng-if=dataSet></div>
</div>
JS:
$scope.dataSet;
var loadFromUrl = function () {
$http.get('https://jsonplaceholder.typicode.com/posts')
.then(function(result){
$scope.dataSet = result.data;
for (var i in $scope.dataSet) {
$scope.dataSet[i].startDate = '2020-12-20T10:00:00Z';
$scope.dataSet[i].endDate = '2020-12-20T11:00:00Z';
}
$scope.schedulerOptions = {
dataSource: $scope.dataSet,
dateSerializationFormat: "yyyy-MM-ddTHH:mm:ssZ",
views: ["day", "workWeek", "month"],
currentView: "day",
currentDate: new Date(),
startDayHour: 9,
endDayHour: 19,
height: 600,
textExpr: "title",
startDateExpr: "startDate",
endDateExpr: "endDate",
allDayExpr: "AllDay"
};
})
};
loadFromUrl();

Add custom marker with store logo in ionic using google map

I am working with ionic and i want to display map marker with store logo. I constructed a default marker and I have lots of store pics or logos which need to be placed within the marker show in above image. I have used cordova geolocation plugin for get current location of user.
Response array like this :
var markers = [{
storeName: "Dib Dab Extract",
profilePic: "img/dibdab.png",
address: "420 Mary Jane Way",
rating: "4",
reviews: "4379",
offer: "100 Free Coins with 1st Purchse",
lat: "53.896408",
long: "-105.991427"
}]
Custom Marker Icon :
var image = {
url: 'img/ic_map_pin_gray.png', // image is 512 x 512
scaledSize: new google.maps.Size(80, 80),
};
Marker set on map like this :
var markerPos = new google.maps.LatLng(record.lat, record.long);
// Add the markerto the map
var marker = new google.maps.Marker({
map: map,
animation: google.maps.Animation.DROP,
position: markerPos,
icon: image,
});
Issue is resolved using Custom Marker. I have done code like this and i get exact marker like i want in above question. So i posted this answer that help anyone who want custom marker like this. i have refer https://humaan.com/blog/custom-html-markers-google-maps/
// Map Initilize function
function initMap() {
var options = {
timeout: 10000,
enableHighAccuracy: true
};
$cordovaGeolocation.getCurrentPosition(options).then(function(position) {
var latLng = new google.maps.LatLng(position.coords.latitude,position.coords.longitude);
var mapOptions = {
center: latLng,
zoom: 15,
disableDefaultUI: true,
mapTypeId: google.maps.MapTypeId.ROADMAP
};
map = new google.maps.Map(document.getElementById("map"), mapOptions);
//Wait until the map is loaded
//Load the markers
loadMarkers();
//});
}, function(error) {
console.log(error);
console.log("Could not get location");
//Load the markers
loadMarkers();
});
}
//load marker using rest api
function loadMarkers() {
CommonService.ShowLoader();
YOUR REST API SERVICE.then(function(res) {
angular.forEach(res, function(value, key) {
var record = value;
console.log(record);
var image = {
url: 'img/ic_map_pin_gray.png', // custom background image (marker pin)
scaledSize: new google.maps.Size(70, 70),
};
var markerPos = new google.maps.LatLng(record.lat, record.long);
//Add the markerto the map
var marker = new google.maps.Marker({
map: map,
animation: google.maps.Animation.DROP,
position: markerPos,
icon: image,
});
var img_src = record.profilePic;
var overlay = new CustomMarker(
markerPos,
map, {image: img_src}
);
});
}).catch(function(error, status, headers, config) {
console.log(error);
});
}
//CustomMarker function
function CustomMarker(latlng, map, args) {
this.latlng = latlng;
this.args = args;
this.setMap(map);
}
CustomMarker.prototype = new google.maps.OverlayView();
CustomMarker.prototype.draw = function() {
var self = this;
var div = this.div;
if (!div) {
div = this.div = document.createElement('img');
div.src = self.args.image;
div.className = 'marker';
div.style.position = 'absolute';
div.style.cursor = 'pointer';
div.style.width = '35px';
div.style.height = '35px';
div.style.borderRadius = '50%';
if (typeof(self.args.marker_id) !== 'undefined') {
div.dataset.marker_id = self.args.marker_id;
}
google.maps.event.addDomListener(div, "click", function(event) {
google.maps.event.trigger(self, "click");
});
var panes = this.getPanes();
panes.overlayImage.appendChild(div);
}
var point = this.getProjection().fromLatLngToDivPixel(this.latlng);
if (point) {
div.style.left = (point.x - 18) + 'px'; // set custom (i set it as i want to set in map )
div.style.top = (point.y - 56) + 'px'; //set custom (i set it as i want to set in map )
}
};
This worked for me.
marker = new MarkerWithLabel({
position: new google.maps.LatLng(item.latitude, item.longitude),
animation: google.maps.Animation.DROP,
labelContent: "My Job Location",
labelAnchor: new google.maps.Point(10, 38),
labelClass: "markLabelsJob", // the CSS class for the label
labelInBackground: false,
icon: 'img/active-job-pin.png',
map: map
});

Openlayers-3 WFS-T (Post feature to postgis via geoserver)

I have a problem with posting features from ol3 into postgis db via geoservers wfs.When i run this code, i only manage to insert gid(pk) and bin columns but the_geom(Geometry) column is empty.
function addInteraction() {
draw = new ol.interaction.Draw({
features: featureOverlay.getFeatures(),
type: /** #type {ol.geom.GeometryType} */ (typeSelect.value)
});
draw.on('drawend', function(evt) {
var feature = evt.feature;
feature.set('bin', 0);
var fid = feature.getId();
var node = format.writeTransaction([feature], null, null, {
gmlOptions: {srsName: "EPSG:3857"},
featureNS: "fiware",
featureType: "nyc_buildings"
});
$.ajax({
type: "POST",
url: "http://192.168.4.33:9090/geoserver/wfs",
data: new XMLSerializer().serializeToString(node),
contentType: 'text/xml',
success: function(data) {
var result = format.readTransactionResponse(data);
feature.setId(result.insertIds[0]);
},
error: function(e) {
var errorMsg = e? (e.status + ' ' + e.statusText) : "";
bootbox.alert('Error saving this feature to GeoServer.<br><br>'
+ errorMsg);
},
context: this
});
});
map.addInteraction(draw);
}
Xml that i get is:
<Transaction xmlns="http://www.opengis.net/wfs" service="WFS" version="1.1.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://www.opengis.net/wfs http://schemas.opengis.net/wfs/1.1.0/WFS-transaction.xsd http://192.168.4.33:9090/geoserver/grp/wfs/DescribeFeatureType?typename=fiware:nyc_buildings">
<Insert>
<nyc_buildings>
<geometry>
<Polygon xmlns="http://www.opengis.net/gml" srsName="EPSG:3857">
<exterior>
<LinearRing srsName="EPSG:3857">
<posList>-12682023.77343518 4567060.841291264 -11077457.675672762 2571137.15870874 -9629434.611838378 5819405.112715591 -12682023.77343518 4567060.841291264
</posList>
</LinearRing>
</exterior>
</Polygon>
</geometry>
<bin>0</bin>
</nyc_buildings>
</Insert>
</Transaction>
And xml that i know it works is:
<wfs:Transaction
service="WFS"
version="1.1.0"
xmlns:fiware="fiware"
xmlns:wfs="http://www.opengis.net/wfs"
xmlns:gml="http://www.opengis.net/gml"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://www.opengis.net/wfs
http://schemas.opengis.net/wfs/1.1.0/WFS-transaction.xsd
http://192.168.4.33:9090/geoserver/grp/wfs /DescribeFeatureType?typename=fiware:nyc_buildings">
<wfs:Insert>
<fiware:nyc_buildings>
<fiware:bin>0</fiware:bin>
<fiware:the_geom>
<gml:MultiSurface srsDimension="2" srsName="http://www.opengis.net/gml/srs/epsg.xml#2908">
<gml:surfaceMember>
<gml:Polygon srsDimension="2">
<gml:exterior>
<gml:LinearRing srsDimension="2">
<gml:posList>988431.501 208900.429 988414.001 208910.222 988393.197 208921.866 988439.703 209005.415 988460.579 208993.729 988481.799 208981.856 988462.619 208948.07 988456.73 208951.37 988442.511 208925.97 988448.961 208922.361 988439.27 208904.93 988435.53 208898.25 988431.501 208900.429</gml:posList>
</gml:LinearRing>
</gml:exterior>
</gml:Polygon>
</gml:surfaceMember>
</gml:MultiSurface>
</fiware:the_geom>
</fiware:nyc_buildings>
</wfs:Insert>
Any idea?
Here is more complete code regarding wfs-t:
var format = new ol.format.WFS({featureNS:"fiware",featureType:'fw_core',schemaLocation:"http://www.opengis.net/wfs \
http://schemas.opengis.net/wfs/1.1.0/WFS-transaction.xsd \
http://192.168.4.33:9090/geoserver/grp/wfs/DescribeFeatureType?typename=fiware:fw_core"});
function addInteraction() {
draw = new ol.interaction.Draw({
features: featureOverlay.getFeatures(),
type: /** #type {ol.geom.GeometryType} */ (typeSelect.value)
});
draw.on('drawend', function(evt) {
// create a unique id
// it is later needed to delete features
// give the feature this id
var feature = evt.feature;
feature.set('geometry', feature.getGeometry());
var node = format.writeTransaction([feature], null, null, {
gmlOptions: {srsName: "EPSG:3857"},
featureNS: "fiware",
featureType: "fiware:fw_core"
});
$.ajax({
type: "POST",
url: "http://192.168.4.33:9090/geoserver/wfs",
data: new XMLSerializer().serializeToString(node),
contentType: 'text/xml',
success: function(data) {
var result = format.readTransactionResponse(data);
feature.setId(result.insertIds[0]);
},
error: function(e) {
var errorMsg = e? (e.status + ' ' + e.statusText) : "";
bootbox.alert('Error saving this feature to GeoServer.<br><br>'
+ errorMsg);
},
context: this
});
});
map.addInteraction(draw);
}
Also when defining vector layer on Geoserver, in publishing tab you must define what column you are using as geometry column.
Another thing, depending on OpenLayers 3 version you might need to use node.impl instead of just node in this line of code:
new XMLSerializer().serializeToString(node.impl)
Hope it helps!
I figured it out,
because the name of the column was geometry i had to set attribute with same name.So what i did is:
draw.on('drawend', function(evt) {
var feature = evt.feature;
feature.set('geometry', feature.getGeometry());
var fid = feature.getId();
var node = format.writeTransaction([feature], null, null, {
gmlOptions: {srsName: "EPSG:3857"},
featureNS: "fiware",
featureType: "nyc_buildings"
});

ExtJS 4: Ext.grid.Panel Ext.PagingToolbar buttons (first, previous, next, last) not passing start and limit parameters

I'm having difficulty getting the paging toolbar to work. The initial load passes the "start" and "limit" parameter to the server proxy and the data loads fine in the grid. However, when clicking the "Next" button in the paging toolbar, the "start" and "limit" parameters don't get passed properly and the web method bombs out because it expects those parameters. If you can help me fix the root problem, that would be awesome. But if not, and you're able to help me override the buttons, that's also fine, so I can put in a temporary fix until I figure out what's wrong.
Exception:
POST http://{domain}/Controls/ObjectList/ObjectListService.asmx/GetObjectList?_dc=1348591244365 500 (Internal Server Error) ext-all-debug.js:36837
Ext.define.request ext-all-debug.js:36837
Ext.define.doRequest ext-all-debug.js:49508
Ext.define.read ext-all-debug.js:39082
Ext.define.load ext-all-debug.js:47668
Base.implement.callParent ext-all-debug.js:3728
Ext.define.load ext-all-debug.js:50160
Ext.define.read ext-all-debug.js:47399
Ext.define.loadPage ext-all-debug.js:50404
Ext.define.nextPage ext-all-debug.js:50409
Ext.define.moveNext ext-all-debug.js:102105
Ext.define.fireHandler ext-all-debug.js:79530
Ext.define.onClick ext-all-debug.js:79520
(anonymous function)
Ext.apply.createListenerWrap.wrap ext-all-debug.js:9171
{"Message":"Invalid web service call, missing value for parameter: \u0027query\u0027.","StackTrace":" at System.Web.Script.Services.WebServiceMethodData.CallMethod(Object target, IDictionary`2 parameters)\r\n at System.Web.Script.Services.WebServiceMethodData.CallMethodFromRawParams(Object target, IDictionary`2 parameters)\r\n at System.Web.Script.Services.RestHandler.InvokeMethod(HttpContext context, WebServiceMethodData methodData, IDictionary`2 rawParams)\r\n at System.Web.Script.Services.RestHandler.ExecuteWebServiceCall(HttpContext context, WebServiceMethodData methodData)","ExceptionType":"System.InvalidOperationException"}
===========================
Source Code:
var itemsPerPage = 30;
var store = new Ext.data.Store({
proxy: new Ext.ux.AspWebAjaxProxy({
url: '/Controls/ObjectList/ObjectListService.asmx/GetObjectList',
actionMethods: {
create: 'POST',
destroy: 'DELETE',
read: 'POST',
update: 'POST'
},
reader: {
type: 'json',
model: 'Object',
totalProperty: 'd.recordCount',
//idProperty: 'object_id',
root: 'd.resultSet'
},
headers: {
'Content-Type': 'application/json; charset=utf-8'
}
}),
pageSize: itemsPerPage,
noCache: false,
//autoLoad: true
autoLoad: {
params: {
//query: '',
start: 0,
limit: itemsPerPage
}
}
});
...
Ext.define('ObjectGrid', {
extend: 'Ext.grid.Panel',
initComponent: function () {
var me = this;
Ext.applyIf(me, {
store: store,
forceFit: true,
autoScroll: true,
height: 750,
loadMask: true,
columns: [
],
...
bbar: Ext.create('Ext.PagingToolbar', {
store: store,
displayInfo: true,
pageSize: 30,
displayMsg: 'Displaying records {0} - {1} of {2}',
emptyMsg: 'No records to display'
// type: 'pagingmemory',
// listeners: {
// afterrender: {
// single: true,
// fn: function (thispaging) {
// thispaging.first.on('click', function () {
// Ext.Msg.alert('first', 'first');
// });
// thispaging.prev.on('click', function () {
// Ext.Msg.alert('prev', 'prev');
// });
// thispaging.next.on('click', function () {
// Ext.Msg.alert('next', 'next');
// });
// thispaging.last.on('click', function () {
// Ext.Msg.alert('last', 'last');
// });
// }
// }
// }
// listeners: {
// 'click' : function(which) {
// alert('you have clicked');
// }
// }
}) // bbar
});
me.callParent(arguments);
}
});
update #1:
The parameters are being lost between these two calls in the stack trace mentioned above.
line 39082:
this.requests.5.options.params = "{}"
(5) being the current object
line 47668:
operation.start = 2
operation.limit = 30
update #2:
Ext.define('Ext.ux.AspWebAjaxProxy', {
extend: 'Ext.data.proxy.Ajax',
require: 'Ext.data',
//processData: false,
buildRequest: function (operation) {
var params = Ext.applyIf(operation.params || {}, this.extraParams || {}),
request;
params = Ext.applyIf(params, this.getParams(params, operation));
if (operation.id && !params.id) {
params.id = operation.id;
}
params = Ext.JSON.encode(params);
request = Ext.create('Ext.data.Request', {
params: params,
action: operation.action,
records: operation.records,
operation: operation,
url: operation.url
});
request.url = this.buildUrl(request);
operation.request = request;
return request;
}
});
Well I guess the trick lies within
// Clone params right now so that they can be mutated at any point further down the call stack
var me = this,
params = operation.params = Ext.apply({}, operation.params, me.extraParams),
request;
I think you can use this to replace your first lines, I guess it should work then.
Please look also at
// Set up the entity id parameter according to the configured name.
// This defaults to "id". But TreeStore has a "nodeParam" configuration which
// specifies the id parameter name of the node being loaded.
if (operation.id !== undefined && params[me.idParam] === undefined) {
params[me.idParam] = operation.id;
}
dunno if you need to update this too.
I tried going back to ExtJS version 4.0.0, but other features in my application are breaking. So I'm sticking with version 4.1.0 and implemented a hack for this proxy so it'll work, so I can have some piece of mind (or is it "peace of mind?").
Ext.define('Ext.ux.AspWebAjaxProxy', {
extend: 'Ext.data.proxy.Ajax',
require: 'Ext.data',
buildRequest: function (operation) {
var params = Ext.applyIf(operation.params || {}, this.extraParams || {}),
request;
params = Ext.applyIf(params, this.getParams(params, operation));
if (params.page == null) {
params.page = operation.page;
params.start = operation.start;
params.limit = operation.limit;
}
if (operation.id && !params.id) {
params.id = operation.id;
}
params = Ext.JSON.encode(params);
request = Ext.create('Ext.data.Request', {
params: params,
action: operation.action,
records: operation.records,
operation: operation,
url: operation.url
});
request.url = this.buildUrl(request);
operation.request = request;
return request;
}
});
//});

Resources