I would like to add in the click event, a line of code that when I click on the chart, grab the content of the data [] in its series, to save it in a variable for future use.
Which one is the syntax to do so? this.chart.series didn't work.
I am planning to pass this to another chart, as data:
This is what I have so far; tried with get() also but I still get undefined errors
chart: {
renderTo: 'chart',
events: {
click:function(event){
extracteddata=this.chart.get('mainseries');
}
},
}
When I print out in console; the only thing that I get is "this"; which return me the whole chart object including everything inside.
Tried so far with
this.series.option.data
this.data
this.series
And neither return the content of the array. I have printed out "this" and I can clearly see the series.data array which is correctly populated.
this.series is an array of series objects, so assuming you want the first series, use:
events: {
click: function (event) {
var someData = this.series[0].data;
}
}
someData here is an array of point objects. If you want just numbers use
this.series[0].yData
and/or
this.series[0].xData
Related
I am attempting to use the getPolygonById method with a map polygon series created using custom GeoJSON data (this is in order to zoom to a polygon with a specific ID). I have followed the instructions provided on creating custom maps.
The Map Polygon Series from the custom GeoJSON data renders and events function correctly (eg to zoom to a polygon or color change on "hit").
However, when calling customSeries.getPolygonById("ExampleID"), the method returns "undefined". Note that the GeoJSON source for customSeries includes the corresponding id field (ie "id": "ExampleID").
That is, despite rendering correctly, the following code returns "undefined":
var customSeries = map.series.push(new am4maps.MapPolygonSeries());
customSeries.geodataSource.url = "/geojson/customSeries.geojson";
customSeries.useGeodata = true;
console.log(customSeries.getPolygonById("ExampleID"));
This contrasts with the return of the JSON object with specified Map Polygon when using an Amcharts map template. For example, the following code returns an object corresponding to the Map Polygon with "US" id:
var worldLow = map.series.push(new am4maps.MapPolygonSeries();
worldLow.useGeodata = true;
worldLow.geodata = am4geodata_worldLow;
console.log(worldLow.getPolygonById("US"));
Is this an issue with my data? Or is something additional required to call getPolygonById on a Map Polygon Series from custom GeoJSON?
Loading data through the DataSource / GeoDataSource object is done asynchronously, so your getPolygonById call is executing before the data has been parsed and loaded into the series. You can either use the done event in the DataSource or datavalidated event in the series to check for whether the data has been loaded before calling getPolygonById
polygonSeries.geodataSource.events.on('done', function() {
// timeout needed as the data isn't complately loaded at this point
setTimeout(function() {
console.log('done: ', polygonSeries.getPolygonById('BCH'))
}, 100)
})
// OR
polygonSeries.events.on('datavalidated', function() {
// check if there's data loaded in the array before looking up
// the polygon
if (polygonSeries.data.length) {
console.log('data loaded', polygonSeries.getPolygonById('BCH'))
}
})
Demo
I'm new to Jetpack Compose and I've spent some hours to find how to make a LazyColumn update what I update my list. I've read that it needs to be a immutable list to update LazyColumn, but I can't seem to get it to work.
The code looks like:
#Composable
fun CreateList() {
var myList : List<DailyItem> by remember { mutableStateOf(listOf())}
myList = getDailyItemList() // Returns a List<DailyItem> with latest values and uses mutable list internally
// Function to refresh the list
val onUpdateClick = {
// Do something that updates the list
...
// Get the updated list to trigger a recompose
myList = getDailyItemList()
}
// Create the lazy column
...
}
I have tried several things and either is the list never updated when tapping the update button or only the first item is updated but not the rest of the items in the list. I looked in the documentation and there it says this, but I don't understand it:
Instead of using non-observable mutable objects, we recommend you use
an observable data holder such as State<List> and the immutable
listOf().
How to update the list so the LazyColumn is updated?
Use SnapshotStateList, the list is mutable. Any modification (add, remove, clear, ...) to the list will trigger an update in LazyColumn.
Similar to mutableListOf() (for MutableList) there is mutableStateListOf() to create a SnapshotStateList.
Extention function swapList() just combines clear() and addAll() calls to replace old list with new list.
fun <T> SnapshotStateList<T>.swapList(newList: List<T>){
clear()
addAll(newList)
}
#Composable
fun CreateList() {
val myList = remember { mutableStateListOf<DailyItem>() }
myList.swapList(getDailyItemList()) // Returns a List<DailyItem> with latest values and uses mutable list internally
// Function to refresh the list
val onUpdateClick = {
// Do something that updates the list
...
// Get the updated list to trigger a recompose
myList.swapList(getDailyItemList())
}
// Create the lazy column
...
}
See the basic idea is to get compose treat the list as state. Now that, you are able to achieve using mutableStateOf(initialValue),
Okay, the process is this,.
We create a variable, initialising it as a mutable state of something
Then we assign that variable to the lazy column. It is not necessary to assign it to the items parameter of the column, but that is our use case here. Otherwise, inside the Composable containing the lazy column, you could just type the name of the variable and even that will work since all we want, is compose to get a message that this variable is being read by the Composable.
Back to the question,
We create a variable, say val mList: List<Int> by remember { mutableStateOf (listOf()) }
Lazycolumn{
items(items = mList){
Text(it)
}
}
Button(onClick = { mList = mList + listOf(mList.size())})
Clicking the button adds a new number to the list, which is reflected in the LazyColumn's UI.
Short: toList() executes before makeMaker causing the markers to have null objects.
Long: In Firestore, I have table and game collections and inside of table, there is a game field(type=reference). With a StreamBuilder, I can access tables. And I iterate through tables and try to fill in their game fields with real data by using get as seen in below;
if (snapshot.hasData) {
tabledocs = snapshot.data.documents;
markers = tabledocs
.map((tabledoc) {
DocumentReference gameref = tabledoc.data['game'];
//game field is a reference type field which points to another collection
gameref.get().then((gdoc) {
tabledoc.data['game'] = gdoc;
Marker marker = makeMarker(tabledoc); //<--------Executes later
return marker;
});
}).toList(); //<--------Executes first
}
Because gameref.get().then() takes time, the toList() at the bottom executes before each marker is generated and added in to markers.
If there are 3 markers returned from Firestore, our markers is an array of 3 null markers. I think makeMarker(..) did not execute yet most probably.
Is there a way for the map method to wait for the gets to finish and then initialize markers array with non-null values? Or can you show me another way to accomplish what I want.
You can either use
await for(var tabledoc of tabledocs) {
}
or if it is not necessary that the items are executed in order (the result will be in the order of the original items though)
var markers = await Future.wait(tabledocs
.map((tabledoc) {
DocumentReference gameref = tabledoc.data['game'];
//game field is a reference type field which points to another collection
var gdoc = await gameref.get();
tabledoc.data['game'] = gdoc;
Marker marker = makeMarker(tabledoc);
return marker;
});
I have a code that is working with a canvas and I'd like to convert it into a layer.
The problem is that I do not want to use the build mechanism of OL3, I just want to use plain javascript.
At the moment, the problem I have is that my handleRender_ function is never called.
Here is my JS code :
ol.layer.MyLayerProperty = {
};
ol.layer.My = function (opt_options) {
var options = opt_options || {};
ol.layer.Layer.call(this, options);
this.on('render', this.handleRender_.bind(this)); //I suspect this is not working
};
ol.inherits(ol.layer.My, ol.layer.Layer);
ol.layer.My.prototype.handleRender_ = function (event) {
console.log('render process'); //never called
};
In fact, to display a canvas "above" openlayers, you simply have to use ImageCanvas.
see http://www.acuriousanimal.com/thebookofopenlayers3/chapter03_04_imagecanvas.html for example
It is quite easy to pass custom data into tooltip formatter by simply adding additional property for each series data item.
But I can't seem to find a way to pass property into xAxis.labels.formatter without using global scoped variables.
Currently I need to pass a string which will help me with custom formatting of label in future.
Anyone knows how to do this?
You can define a custom property in labels options object. Actually you can define a property wherever you want, but I assume this place fits the most.
In a formatter callback you can access to it via this.axis.options.labels['customProperty'].
xAxis: {
categories: ['Foo', 'Bar', 'Foobar'],
labels: {
formatter: function () {
return this.value + ' ' + this.axis.options.labels.myString;
},
myString: 'myString'
}
},
Example: http://jsfiddle.net/0o4xe4rb/