Azure Maps - Unable to set layer options 'offset' from point properties without browser warnings - azure-maps

I'm trying to use the offset parameters for the text label in relation to the position of the point (marker) on the map.
In my app, the user sets their preference to the x & y-axis offset values, which when changed, update the map point properties. I then need to use data-driven expressions to pull the values from each map point properties when updating the point layer options.
When the point is first created, the offset property of the point is set as below:
offset: [0, 0],
When updating the point layer, I've tried using the expression formulas below, but none of them are working without getting warnings in the browser debug console.
layers.pointLayer.setOptions({
iconOptions: {
offset: [ // ******NEEDS FIXING*******
'case', // Use a conditional case expression.
['has', 'offset'], // Check to see if feature has an "offset" property
//["length", ["array", ["get", "offset"]]] // not working
['get', 'offset'], // not working without browser warning
//['get', ['literal', [0, 0]]], // not working
//['literal', [0,0]], // working but not relevant, set locally, not pulling value from properties!!!
'literal', [0, 0]] // If it doesn't, default to array [0,0] (x & y-axis).
]
}
})
If using the example ['get', 'offset'], in the expression, although I can actually modify the offset and it works on the map as shown in the screenshot, I get the following warning in the browser debug console:
I'd like to have a warning free environment as any debug warnings. I obviously need to get the formatting set correctly in the data driven expression when setting the options for the layer (2nd code sample) but none of the syntax I've tried so far are working correctly.
I also tried studying the MS example here, but it seems they don't actually pull the offset values from the map point properties, they are setting the layer options directly from the user form which is no good unless i wanted to implement a global change for all points that belong to this particular layer.

Related

How to map array of objects

I have some problems mapping an array of objects in JS.
This is how the response looks in my console:
[{...}]
...and when I expand it I get this:
0:{id:0, document:{...}}
1:{id:1, document:{...}}
Usually the response I get is always without this number in front of each object, like this:
{id:0, document:{...}
{id:1, document:{...}
I tried every approach I know and I cant't manage to handle it.
The goal is to take each value out of "document" property and dynamically display it in some kind of table.
This is the way the browser devtools decides to display the array, but it is actually correct, if I'm not mistaken you're still dealing with an array.
You can verify this by logging the following:
(Replace myVar with the variable name you chose for your response array)
console.log(Array.isArray(myVar))
If it outputs true then you're fine and you are dealing with an array.

react-chartjs: difference between `scales.x`/`xAxes`/`xAxes[]`

I'm using react-chartjs-2 with Typescript.
I'm very confused with the interface of chartjs (perhaps this is due to severe API changes beneath versions and information running around online without clearly stating the version).
What is the difference between the following options:
options.scales.x: {}
options.scales.xAxes: {}
I thought this was equal to the above, but under certain circumstances I could not get options.scales.xAxes.min working. So I resorted to using x.
options.scales.xAxes: [{}]
I see many examples using this syntax (especially here on SO). However, using it myself results in a type error.
options.scales.xAxes: [{}] is V2 syntax, here all the x axes are grouped in a single array, same for all the y axes.
In v3 all the scales are their own object within the scales object where the key of the object is your scale ID.
by default you should use options.scales.x to configure the default x axis. But to make things a bit easyer chart.js looks at the fist letter of the object to determine its type so if you pass options.scales.xAxes it should result in the same if you dont have any other scales configured

Azure Maps - How to use AND logic in Data Driven Style Expressions

When using the layer.setOptions function, I need to figure out how to combine two data driven style expressions so that both expressions are respected when using the filter property.
Why? In my project I am filtering the visbility of map objects (features likes shapes, points etc) using layer groups whereby each feature when created or updated, I set a property value with the layer group that it belongs to. So later the user can choose whether turn the visibility on or off for groups of map objects, example below:
In addition to filtering the visbility of my map objects by layer group, I also need to apply a filter so each layer type will only render certain geomtry types. The MS docs explanation on this is shown here:
Now when I set the options for any of the layers used, I need to be able to combine the two filters into one argument-->
The first filter argument would filter the layers by layer groups:
var filter = ['in', ['get', 'layerGroup'], ['literal', layerGroupsArray]]
The second filter would ensure that only certain geomtry types are rendered for that layer:
var filter = ['==', ['geometry-type'], 'LineString']; // other shapes could be 'Polygon' / 'Circle' etc
Note: Using either of the above filters in isolation both work in their own right, but I dont know how to combine both arguments together, its almost like we need a logical AND function, which i tried but the browser debug throws an error:
var combinedFilterExample = ['in', ['get', 'layerGroup'], ['literal', layerGroupsArray]] & ['==', ['geometry-type'], 'LineString'];
Eventually I found a snippet from the MS Docs that explains how to set the expression so it requires all arguments to be respected, they use the 'all' attribute to do this which i beleive achieves a simialr objective to using an AND logic operator.
So from my original question, we can combine two filter expressions into one argument as follows:
var lineLayerFilter = ['all', ['==', ['geometry-type'], 'LineString'], ['in', ['get', 'layerGroup'], ['literal', layerGroupsArray]]]
If you want to combine more expressions in the argument then we simply add more to the argument, and it looks to be we dont need to add any closing sqaure brackets at the end. Further example:
var polygonOuterLayerFilter = ['all', ['==', ['geometry-type'], 'Polygon'], ['==', ['geometry-type'], 'LineString'], ['in', ['get', 'layerGroup'], ['literal', layerGroupsArray]]]
MS Docs reference here: https://learn.microsoft.com/en-us/azure/azure-maps/data-driven-style-expressions-web-sdk#aggregate-expression

Kendo Chart set skip after load using Angular

Im using Angular Kendo - Im not sure if thats really relevant only to say its not as 'simple' as calling refresh. - I have two scope variables one is the Kendo DataSource the other is the Kendo Chart Options which are assigned like this
$scope.ChartOptions = {
// All The other Chart Stuffs
dataSource : $scope.ChartDataSource
}
<div kendo-chart k-options="ChartOptions" />
This works fine - the issue is that the chart data can vary quite a bit and the area I'm using is small so what happens is the value axis ends up looking okay with values of just 2 or 3 but when you get to 20 or more the labels bunch up is there some way to reset the options after the data is retrieved. Maybe by changing the valueaxis skips etc.
What you are looking for is actually the CategoryAxis Step value. Based upon your data, you need to figure out what the max value is, and then calculate a reasonable step value that will appropriately render out your chart control based upon the space that you have. I can't really give you an example, as this will be entirely dependent upon your data and will likely require a bit of trial and error til you land on a calculation that yields acceptable results.
Documentation for the CategoryAxis step: http://docs.telerik.com/kendo-ui/api/dataviz/chart#configuration-categoryAxis.labels.step
Here is an example for finding the maximum data point:
var data = [1, 3, 4, 9, 10];
var max = Math.max.apply(Math, data);
//code here to do some kind of calculation of step value
Once you know what your appropriate step value should be based upon your data, you can then create your chart and set the CategoryAxis.Labels.Step value to it during grid creation.

quering for objects with angularFireCollection?

I used the implicit method for retrieving data objects:
setData = function(segment){
var url = 'https://myFireBase.firebaseio.com/';
var rawData = angularFire(url+segment,$rootScope,'data',{});
rawData.then(function(data){
// sorting and adjusting data, and then broadcasting and/or assinging
}
}
This code is located inside a service that gets called from different locations, by development stages it'll probably be around 100 - 150 so I got out of the controllers and into a service, but now firebase data-binding would obviously over-write the different segments so I turned back to explicit methid, to have the different firebases only sending the data to site instead of data-binding and over-writing each other:
var rawData = angularFireCollection(url+segment);
And right there I discovered why I chose the implicit in the first place: There's an argument for the typeof, i could tell firebase if I'm calling a string, an array, an object etc. I even looked at the angularfire.js and saw that if the argument is not given, if falls back to identifying it as an array by default.
Now, I'm definitely going to move to the explicit method (that is, if no salvation comes with angular2.0), and reconstructing my firebase jsons to fit the array-only policy is not that big of a deal, but surely there's an option to explicitly call objects, or am I missing something?
I'm not totally clear on what the question is - with angularFireCollection, you can certainly retrieve objects just fine. For example, in the bundled chat app (https://github.com/firebase/angularFire/blob/gh-pages/examples/chat/app.js#L5):
$scope.messages = angularFireCollection(new Firebase(url).limit(50));
Each message is stored as an object, with its own unique key as generated by push().
I'm also curious about what problems you found while using the implicit method as your app grew. We're really looking to address problems like these for the next iteration of angularFire!

Resources