Export AmCharts to image/pdf in React application - reactjs

Working on an application bootstrapped with create-react-app.
I need to export amChart to jpg/png/pdf formats.
I'm trying to export like in this codepen I've found: codepen export amchart example
var chart = AmCharts.makeChart("chart-header", {
"type": "pie",
"theme": "light",
"dataProvider": [ {
"country": "Czech Republic",
"litres": 301.9
}, {
"country": "Austria",
"litres": 128.3
}, {
"country": "UK",
"litres": 99
}, {
"country": "The Netherlands",
"litres": 50
}],
"valueField": "litres",
"titleField": "country",
"export": {
"enabled": true,
"menu": []
}
})
chart["export"].capture({}, function() {
this.toPNG({}, function(base64) {
console.log(base64)
})
})
But it doesn't work in my case. It gives me: Uncaught TypeError: chart.export.capture is not a function all the time.

So.. right or wrong, below is the simplified solution I've found.
On click "export" button, I make this.setState({ shouldExportChart: true }). In the "render" event listener I check whether it's true, if so, perform export and set to false.
In the same way, calling this.toJPG() we can export to JPG format.
For PDF generation I used jspdf, for archiving - jszip.
Dependencies in package.json:
"#amcharts/amcharts3-react": "^3.0.3",
"amcharts3": "^3.21.13",
"amcharts3-export": "github:amcharts/export"
"file-saver": "^1.3.3",
"fabric-webpack": "^1.6.0-rc.1"
Component.jsx:
import 'amcharts3'
import AmCharts from '#amcharts/amcharts3-react'
import 'amcharts3-export'
import 'fabric-webpack'
import FileSaver from 'file-saver'
const chartConfig = {
options: {
...,
"export": {
"enabled": true,
"menu": []
},
"listeners": [
{
event: 'rendered',
method: (e) => {
if (window.fabric) {
e.chart.export.capture({}, function () {
this.toPNG({}, function (base64) {
this.toBlob({
data: base64,
type: 'image/png'
}, (blob) => {
FileSaver.saveAs(blob, 'chart.png')
})
})
})
}
}
}
]
}
}
<AmCharts.React {...chartConfig} />

Related

React rest call map result to selectbox with avatar and label per option

Hi here is rest response:
[
{
"self": "https://your-domain.atlassian.net/rest/api/3/project/EX",
"id": "10000",
"key": "EX",
"name": "Example",
"avatarUrls": {
"48x48": "https://your-domain.atlassian.net/secure/projectavatar?size=large&pid=10000",
"24x24": "https://your-domain.atlassian.net/secure/projectavatar?size=small&pid=10000",
"16x16": "https://your-domain.atlassian.net/secure/projectavatar?size=xsmall&pid=10000",
"32x32": "https://your-domain.atlassian.net/secure/projectavatar?size=medium&pid=10000"
},
"projectCategory": {
"self": "https://your-domain.atlassian.net/rest/api/3/projectCategory/10000",
"id": "10000",
"name": "FIRST",
"description": "First Project Category"
},
"simplified": false,
"style": "classic",
"insight": {
"totalIssueCount": 100,
"lastIssueUpdateTime": "2022-12-08T07:09:19.702+0000"
}
},
{
"self": "https://your-domain.atlassian.net/rest/api/3/project/ABC",
"id": "10001",
"key": "ABC",
"name": "Alphabetical",
"avatarUrls": {
"48x48": "https://your-domain.atlassian.net/secure/projectavatar?size=large&pid=10001",
"24x24": "https://your-domain.atlassian.net/secure/projectavatar?size=small&pid=10001",
"16x16": "https://your-domain.atlassian.net/secure/projectavatar?size=xsmall&pid=10001",
"32x32": "https://your-domain.atlassian.net/secure/projectavatar?size=medium&pid=10001"
},
"projectCategory": {
"self": "https://your-domain.atlassian.net/rest/api/3/projectCategory/10000",
"id": "10000",
"name": "FIRST",
"description": "First Project Category"
},
"simplified": false,
"style": "classic",
"insight": {
"totalIssueCount": 100,
"lastIssueUpdateTime": "2022-12-08T07:09:19.702+0000"
}
}
]
I want to make select bobx having
<option value={data.id}><Img {data.16x16}/>data.label</option>
But result would be all projects if company has multiple projects so select box values have to map or loop into react
<Select options="result">
Im stuck as my code displays only label not any image there.
Another problem is that using data.avatarUrls.16x16 does not compile. VSCode says expecting "," and puts red underline to 16x16
Here is my code a lot is broken here because I have tested a lot ways but no luck
import React, { useState } from 'react';
import Select from 'react-select'
import { components } from 'react-select';
//Kun selectbox
const handleChange = event => {
//console.log(event.target.value);
setSelected(event.target.value);
};
//Palauttaa projectit json taulukon
const getProjects = async () => {
//Matti tähän sitten atlasion cmpany projection haku
const response = await api.asUser().requestJira(route`/rest/api/3/project`, {
headers: {
'Accept': 'application/json'
}
});
const data = await response.json();
//Mapataa hausta tarvittavat tiedot
const result = data.map(function (item, i) {
console.log('test');
return [
{
label: item.name,
value: item.id,
avatar: item.avatarUrls.16x16
}
]
})
return result
}
function Projects() {
//haetaan atlasiansita projectit array
const p = getProjects
//asetetaan state selectbox muutokselle
const [selected, setSelected] = useState(p.id);
return (
<div className='projects'>
<Select
className='select-projects'
options={p}
onChange={handleChange}
/>
</div>
);
}
export default Projects

I am trying to call Weather API using React and Axios I am trying to console.log the result but its saying the undefined... :(

When I am trying the console log the state its saying Undefined.. I also placed the JSON file.
I have posted the endpoint json file here. I believe there is an issue while hooking up json.
When I am trying the console log the state its saying Undefined.. I also placed the JSON file.
I have posted the endpoint json file here. I believe there is an issue while hooking up json.
class App extends Component {
state = {
content: [{ coord: "" }, { base: "" }]
};
componentDidMount() {
axios
.get(
"https://api.openweathermap.org/data/2.5/weather?q=berlin&appid=240ef553958220e0d857212bc790cd14"
)
.then(res => {
this.setState({
content: [
{
coord: res.data.coord
},
{ base: res.data.base }
]
});
});
}
render() {
console.log(this.state.content.coord);
return (
<div className="App center">
<h2 className="blue-text">Weather App</h2>
<div></div>
<Weather />
</div>
);
}
}
export default App;
JSON endpoint goes here....
{
"coord": {
"lon": 13.41,
"lat": 52.52
},
"weather": [
{
"id": 803,
"main": "Clouds",
"description": "broken clouds",
"icon": "04n"
}
],
"base": "stations",
"main": {
"temp": 276.88,
"feels_like": 268.47,
"temp_min": 275.37,
"temp_max": 278.15,
"pressure": 994,
"humidity": 80
},
"visibility": 10000,
"wind": {
"speed": 9.3,
"deg": 240,
"gust": 14.4
},
"clouds": {
"all": 75
},
"dt": 1580260557,
"sys": {
"type": 1,
"id": 1275,
"country": "DE",
"sunrise": 1580280826,
"sunset": 1580312685
},
"timezone": 3600,
"id": 2950159,
"name": "Berlin",
"cod": 200
}
As content is an array type you can access coord or base directly. Instead change it to an object or access it based on array index like this.
this.state.content[0].coord / this.state.content[1].base
If you change content to object type you can access coord or base directly as i did it here
sample code:
state = {
content: { coord: "", base: "" }
};
after request fetch you can update state something like this.
this.setState({
content: { coord: res.data.coord, base: res.data.base }
});
You can make your state look like below which make reading and accessing the data easier.
state = {
content: {
coord: "",
base: "",
},
}
and your setState like below:
this.setState({
content: {
coord: res.data.coord,
base: res.data.base
}
})

Render JSON data from API call in react

Working on an app using the google maps API for geolocation with Reactjs. My aim right now is to simply render the entire JSON data to the window (will be used later). No errors, but nothing is rendering to the page. Am I trying to access the data inccorrectly?
class App extends Component {
constructor () {
super();
this.state = {
isLoaded: false,
results: {}
};
}
componentDidMount() {
fetch(geo_url)
.then(res => res.json())
.then(
(result) => {
this.setState({
isLoaded: true,
results: result.results
});
},
(error) => {
this.setState({
isLoaded: true,
error
});
}
)
}
render() {
const {error, isLoaded, results} = this.state;
if (error) {
return <div>Error: {error.message} </div>;
} else if (!isLoaded) {
return <div>Loading...</div>;
} else {
return (
<div className="App">
Location Data:
{results.geometry}
</div>
);
}
}
}
Below is a sample of the JSON i'm trying to access:
{
"results": [
{
"address_components": [
{
"long_name": "1600",
"short_name": "1600",
"types": [
"street_number"
]
},
{
"long_name": "Amphitheatre Parkway",
"short_name": "Amphitheatre Pkwy",
"types": [
"route"
]
},
{
"long_name": "Mountain View",
"short_name": "Mountain View",
"types": [
"locality",
"political"
]
},
{
"long_name": "Santa Clara County",
"short_name": "Santa Clara County",
"types": [
"administrative_area_level_2",
"political"
]
},
{
"long_name": "California",
"short_name": "CA",
"types": [
"administrative_area_level_1",
"political"
]
},
{
"long_name": "United States",
"short_name": "US",
"types": [
"country",
"political"
]
},
{
"long_name": "94043",
"short_name": "94043",
"types": [
"postal_code"
]
}
],
"formatted_address": "1600 Amphitheatre Pkwy, Mountain View, CA 94043, USA",
"geometry": {
"location": {
"lat": 37.422617,
"lng": -122.0853839
},
"location_type": "ROOFTOP",
"viewport": {
"northeast": {
"lat": 37.4239659802915,
"lng": -122.0840349197085
},
"southwest": {
"lat": 37.4212680197085,
"lng": -122.0867328802915
}
}
},
"place_id": "ChIJ2eUgeAK6j4ARbn5u_wAGqWA",
"plus_code": {
"compound_code": "CWF7+2R Mountain View, California, United States",
"global_code": "849VCWF7+2R"
},
"types": [
"street_address"
]
}
],
"status": "OK"
}
First render occurs before results are retrieved. Check in render() whether results exist already. If not, display a 'loading' message.
In addition to that, fix your handling of error while trying to retrieve data. You are setting a state.error variable which was not defined. Then, in render, display an error message if loading is done but there is an error.
First, you have to do :
<div className="App">
{this.state.results.geometry}
</div>
or
render() {
const {results} = this.state
return (
<div className="App">
{results.geometry}
</div>
);
}
}
But Like #Yossi saids, you result are not defined in you first render. That's why you have : "results not defined". You can use "lodash" to force your render. It's works even if I don't know if it's a good practice
You can test :
import _ from 'lodash';
render() {
const {results} = this.state
return (
{!_.isEmpty(results) &&
<div className="App">
{results.geometry}
</div>
}
);
}
It should be works :)
PS : sorry for my bad english ;)
You can set in state a key for error: false.
In componentDidMount its better to use then and catch for errors
componentDidMount() {
fetch(geo_url)
.then(res => res.json())
.then(
(result) => {
this.setState({
isLoaded: true,
results: result.results
});
},
(error) => {
this.setState({
isLoaded: true,
error
});
}
).catch(error) {
this.setState({
isLoaded: true,
error
})
}
}

Can't show data from local json file in browser

I want to show JSON data in browser so that model, provider, storage and condition displays in separate divs.
There is no error in console and i can't figure out where is the problem.
Link updated for stackblitz, kindly have a look into it.
Github Repo
Here is the link for stackblitz.
iphone.json
{
"model": [
"iPhone 5",
"iPhone 5s",
"iPhone SE"
],
"provider": [
"Unlocked",
"AT&T"
],
"storage": [
"16",
"32"
],
"condition": [
"Brand New",
"Mint"
]
}
sell.service.ts
import { Injectable } from '#angular/core';
import { Observable } from "rxjs/Observable";
import { Http, Response } from "#angular/http";
import { HttpClient} from '#angular/common/http';
import "rxjs/add/operator/map";
export interface Staticdata {
model: Array<Model>;
provider: Array<Provider>;
storage: Array<Storage>;
condition: Array<Condition>;
}
export interface Model {
name: string;
}
export interface Provider {
carrier: string;
}
export interface Storage {
size: number;
}
export interface Condition {
quality: string;
}
#Injectable()
export class SellService {
fileUrl = '../static-data/iphone.json';
constructor(public http:HttpClient) {}
getData(){
return this.http.get(this.fileUrl);
}
}
sell-iphone.component.ts
import { Component, OnInit } from '#angular/core';
import { SellService, Staticdata } from "../shared/sell.service";
import * as data from "../static-data/iphone.json";
#Component({
selector: 'app-sell-iphone',
templateUrl: './sell-iphone.component.html',
styleUrls: ['./sell-iphone.component.css'],
providers: [ SellService ]
})
export class SellIphoneComponent implements OnInit {
constructor(public sellService: SellService){
}
ngOnInit() {}
staticData : Staticdata;
showData(){
return this.sellService.getData().subscribe((data: Staticdata) => this.staticData = {
model: data.model,
provider: data.provider,
storage: data.storage,
condition: data.condition
});
}
}
your json must be like:
{
"model": [
{
"name": "iPhone 5"
},
{
"name": "iPhone 5s"
},
{
"name": "iPhone SE"
}
],
"provider": [
{
"carrier": "Unlocked"
},
{
"carrier": "AT&T"
}
],
"storage": [
{
"size": "16"
},
{
"size": "32"
}
],
"condition": [
{
"quality": "Brand New"
},
{
"quality": "Mint"
}
]
}
Or you must transform the data you received. You can do it in the service better than in the component.
getData(){
return this.http.get(this.fileUrl).pipe(map((res:any)=>{
return {
model:res.model.map(m=>{return {name:m}}),
provider:res.provider.map(p=>{return{carrier:p}}),
storage:res.storage.map(s=>{return{size:s}}),
condition:res.condition.map(c=>{return{quality:c}})
}
})
);
}
If you're using angular-cli, you must put your file.json in the folder "assets"

AMcharts Map in angular js

I am currently working on AM Charts Maps. I want to implement below link in angularjs. How do I convert into angular js? Should i have to implement directive?
link
<div id="chartdiv"></div>
You can add the following files for the component.
map.component.ts
import { Component } from '#angular/core';
#Component({
selector: 'app-root',
templateUrl: './map.component.html',
styleUrls: ['./map.component.css']
})
export class MapComponent {
private id = "mapdiv";
private options;
makeChartConfig() {
return {
"type": "map",
"theme": "light",
"colorSteps": 10,
"dataProvider": {
"map": "indiaLow",
"areas": [{
"id": "IN-AN",
"value": 4447100
}, {
"id": "IN-AP",
"value": 626932
}, {
"id": "IN-KA",
"value": 5130632
}]
},
"areasSettings": {
"autoZoom": true
},
"valueLegend": {
"right": 10,
"minValue": "little",
"maxValue": "a lot!"
}
};
}
ngOnInit() {
this.options = this.makeChartConfig();
}
}
map.component.html
<amCharts [id]="id" [options]="options" [style.width.%]="100" [style.height.px]="500"></amCharts>

Resources