I am using chartist.js and I am using the chartist within reactjs component.
I am referring this http://gionkunz.github.io/chartist-js/examples.html#simple-pie-chart
chartist.js:
var Chartist = {
version:'0.9.5'
}
(function (window, document, Chartist) {
var options = {
labelInterpolationFnc: function(value) {
return value[0]
}
};
var responsiveOptions = [
['screen and (min-width: 640px)', {
chartPadding: 30,
labelOffset: 100,
labelDirection: 'explode',
labelInterpolationFnc: function(value) {
return value;
}
}],
['screen and (min-width: 1024px)', {
labelOffset: 80,
chartPadding: 20
}]
];
})();
Reactjs component:
import React, { Component } from 'react';
var data = {
labels: ['Bananas', 'Apples', 'Grapes'],
series: [20, 15, 40]
};
showPieChart(data){
new Chartist.Pie('.ct-chart', data, options, responsiveOptions);
}
class Chart extends Component {
render(){
return(
<div>
<div className="center">
{showPieChart}
</div>
</div>
)}
}
export default Chart;
Nothing is displayed on web page. How can I access vanilla javascript inside react component.
Your question is a little bit misleading, and can be interpreted in two ways.
#1. If you're asking how to integrate Chartist library with React, here's how you can do it:
There's a wrapper library, that already did it for us: https://www.npmjs.com/package/react-chartist
You can use it as follow (example taken from their repo):
import React from 'react';
import ReactDOM from 'react-dom';
import ChartistGraph from 'react-chartist';
class Pie extends React.Component {
render() {
var data = {
labels: ['W1', 'W2', 'W3', 'W4', 'W5', 'W6', 'W7', 'W8', 'W9', 'W10'],
series: [
[1, 2, 4, 8, 6, -2, -1, -4, -6, -2]
]
};
var options = {
high: 10,
low: -10,
axisX: {
labelInterpolationFnc: function(value, index) {
return index % 2 === 0 ? value : null;
}
}
};
var type = 'Bar'
return (
<div>
<ChartistGraph data={data} options={options} type={type} />
</div>
)
}
}
ReactDOM.render(<Pie />, document.body)
#2. If you generally asking how to integrate other libraries into React, then I recommend you to check the official React docs, because there's a really good tutorial about the topic - Integrating with Other Libraries
So, if you don't want to use the wrapper library (react-chartist), then you can check its main component too. It's a great starting point (that follows React recommendations) to understand how to create your own wrapper: https://github.com/fraserxu/react-chartist/blob/master/index.js
Related
So I'm using Handsontable library in React to create excel like tables, where HotTable is library component with some options, like contextMenu - modal window , and columns.
Issue is that if I specify columns in HotTable component , in modal window insert/remove column functionality is disabled/grayed-out , not removed. How to enable it?
import { useMemo } from 'react'
import HotTable from '#handsontable/react';
import { registerAllModules } from 'handsontable/registry';
import { ColumnSettings, GridSettings } from "handsontable/settings";
import 'handsontable/dist/handsontable.full.min.css';
registerAllModules();
const MIN_COLS = 30;
const MIN_ROWS = 500;
const data = [
['', 'Tesla', 'Volvo', 'Toyota', 'Ford', 'Audi'],
['2019', 10, 11, 12, 13],
['2020', 20, 11, 14, 13],
['2021', 30, 15, 12, 13]
];
export const excelTables = () => {
const columns = [...new Array(MIN_COLS)].map(
() =>
({
// some key : value pairs -- super important
} as ColumnSettings)
);
return (
<HotTable
data={data}
rowHeaders={true}
colHeaders={true}
contextMenu={true}
columns={columns}
licenseKey={ "non-commercial-and-evaluation"}
/>
);
};
with columns option in HotTable component
without columns option in HotTable component
Columns - in docs said that this option overwrites the top-level grid options. This is just minimal reproducible example, in project I need to specify columns option.
I have a bubble map chart that shows the location of cities on the map. The map has the default label but I want to use a custom react component as the label on the map. This is my source code but it has error and doesn't work:
import React, { Component, Fragment } from "react";
import Highcharts from "highcharts";
import HighchartsReact from "highcharts-react-official";
import HighchartsMap from "highcharts/modules/map";
import mapData from "#highcharts/map-collection/countries/gb/gb-all.geo.json";
import proj4 from "proj4";
import CustomLabel from "./CustomLabel";
HighchartsMap(Highcharts);
class BubbleMapChart extends Component {
render() {
const options = {
chart: {
map: "countries/gb/gb-all",
proj4
},
series: [
{
name: "countries",
nullColor: "#fff",
showInLegend: false,
mapData: mapData
},
{
// Specify points using lat/lon
type: "mapbubble",
// PAY ATTENTION TO THIS SECTION - USE A CUSTOM LABEL COMPONENT
dataLabels: {
enabled: true,
format: <CustomLabel name={"point.name"} />
},
minSize: "5%",
maxSize: "15%",
showInLegend: true,
data: [
{
name: "London",
lat: 51.507222,
lon: -0.1275
},
{
name: "Birmingham",
lat: 52.483056,
lon: -1.893611
}
]
}
]
};
return (
<HighchartsReact
highcharts={Highcharts}
options={options}
constructorType={"mapChart"}
/>
);
}
}
and this is a customLabel component as an example:
import React, { Component } from "react";
class CustomLabel extends Component {
render() {
return (
<div>
{/* Doesn't show this Division (actually doesn't apply the style ...) */}
<div
style={{ BackgroundColor: "red", width: "10px", height: "10px" }}
></div>
<span>{this.props.name}</span>
<br />
{/* Doesn't show the red bullet inside the text */}
<Badge color="#f50" text={this.props.name} />
</div>
);
}
}
export default CustomLabel;
How can I customize the data label in highcharts? actually I want to use a custom component as the label.
Use ReactDOMServer and renderToStaticMarkup or renderToString method in formatter function for data labels:
dataLabels: {
enabled: true,
formatter: function () {
return renderToStaticMarkup(<CustomLabel name={this.point.name} />);
}
}
Live demo: https://codesandbox.io/s/highcharts-react-demo-forked-40icn?file=/demo.jsx
Docs: https://reactjs.org/docs/react-dom-server.html
API Reference: https://api.highcharts.com/highmaps/series.mapbubble.dataLabels.formatter
Or if you need to use some reactive logic inside CustomLabel take advantage of Portals in React.
Docs: https://reactjs.org/docs/portals.html
Example: https://www.npmjs.com/package/highcharts-react-official#how-to-add-react-component-to-a-charts-element
Does anyone here use or have used Vis.js in any project? I'm trying to integrate Vis-network with React, and I even managed to, but I can't manipulate it in any way.
In the examples provided by Vis.js itself, they use the javascript code within the same html page to generate the canvas. As I'm in React, I created a VisNetwork component, and called it in App.js to test it. I even managed to generate the image, it really appeared, but I can't manipulate it.
For example, the canvas area of the example is being 600x400 (example link), but the canvas area generated by React is being 500x150. Through App.css I was able to change the width that used 100% before, but the height could not be manipulated. Anyway, I'll leave the code here.
network.js
import React, { Component, createRef } from "react";
import { DataSet, Network } from 'vis-network/standalone/umd/vis-network.min';
// Create an array with nodes
const nodes = new DataSet([
{id: 1, label: 'Node 1'},
{id: 2, label: 'Node 2'},
{id: 3, label: 'Node 3'},
{id: 4, label: 'Node 4'},
{id: 5, label: 'Node 5'}
]);
// Create an array with edges
const edges = new DataSet([
{from: 1, to: 3},
{from: 1, to: 2},
{from: 2, to: 4},
{from: 2, to: 5}
]);
// Provide the data in the vis format
const data = {
nodes: nodes,
edges: edges
};
const options = {
autoResize: true,
height: '100%',
width: '100%'
};
// Initialize your network!
class VisNetwork extends Component {
constructor() {
super();
this.network = {};
this.appRef = createRef();
}
componentDidMount() {
this.network = new Network(this.appRef.current, data, options);
}
render() {
return (
<div ref={this.appRef} />
);
}
}
export default VisNetwork;
In App.js, I imported VisNetwork and called it inside the div:
import React from 'react';
import './App.css';
import VisNetwork from './network';
function App() {
return (
<div className="App">
<VisNetwork />
</div>
);
}
export default App;
App.css
.App {
text-align: center;
width:500px;
height:500px;
border:solid;
background-color:white;
}
Please do not negative this post without responding. It harm rather than helps. Thanks.
I suggest the reason that set option width and height 100% not working is that the network is attaching on a div which height and width is not defined, so you could try the code below:
const options = {
autoResize: ture,
height: '100%',
width: '100%'
};
// Initialize your network!
class VisNetwork extends Component {
constructor() {
super();
this.network = {};
this.appRef = createRef();
}
componentDidMount() {
this.network = new Network(this.appRef.current, data, options);
}
render() {
let containerStyle = { //define container width and height.
width:"500px",
height:"500px",
}
return (
<div style={containerStyle} ref={this.appRef} />
);
}
}
export default VisNetwork;
If code above doesn't work , I would suggest use this.network.setSize(width, height) to force the canvas to change.
Another way to solve this is create a constant that takes the height size of the DOM and set the constant to the height of options.
const myHeight = Math.round(parseInt(window.innerHeight) * 0.7) + 'px';
const options = {
autoResize: true,
height: myHeight
};
Thus, it is possible to control the percentage.
I am trying to render a Line chart using react-chartjs-2. Right now it works fine when I pass in static props to the Line Component. But, when I fetch data from an API, set it to a variable, then pass that variable as the prop. My Line Component is not re-rendering with the new data.
I am logging the props being passed into the Line Component and I can see it first arrives as null and then I receive the good data from the API. So it looks like the Line Component is not re-rendering after receiving the props? I am probably doing this wrong. Please help.
import React from "react";
import { Line } from "react-chartjs-2";
export default class ExpenseChart extends React.Component {
constructor(props) {
super(props);
this.state = {
marketData: [100, 200, 300],
chartData: {
labels: this.props.monthNames,
datasets: [
{
backgroundColor: "rgba(142, 243, 197, 0.5)",
pointBackgroundColor: "#fff",
pointHoverBackgroundColor: '#fff',
pointStyle: "circle",
label: "Monthly Expenses",
borderColor: "#2be1d8",
borderWidth: 3,
borderJoinStyle: "round",
lineTension: 0.3,
fontColor: "#fff",
hitRadius: 5,
hoverRadius: 8,
radius: 4,
data: this.props.monthExpenses
},
],
},
};
}
render() {
console.log("why no names", this.props.monthNames)
return (
<div className="expenseChart">
<h2 className="expenseChart__name">{this.props.graphname}</h2>
<Line
data={this.state.chartData}
options={{
maintainAspectRatio: false,
responsive: true,
aspectRatio: 3,
scales: {
yAxes: [
{
ticks: {
display: false,
},
},
],
},
layout: {
padding: {
right: 10,
},
},
}}
/>
</div>
);
}
}
And then the parent component is connected to a redux store and it looks like this:
import React from "react";
import { connect } from 'react-redux';
import ExpenseChart from "../elements/ExpenseChart";
import { fetchExpenses } from '../../actions/index';
class Dashboard extends React.Component {
componentDidMount() {
this.props.dispatch(fetchExpenses());
}
render() {
let labels = this.props.months && this.props.months;
return (
<main className="dashboard">
<ExpenseChart
monthNames={labels}
monthExpenses={["123", "123", "12312", "12341", "231231", "1231", "1231"]}
// I am receiving monthExpenses props into the ExpenseChart component
// but not monthNames
/>
</main>
);
}
}
const mapStateToProps = state => ({
auth: state.app.auth,
months: state.app.months,
});
export default connect(mapStateToProps)(Dashboard);
I've done something similar before, fetching data from an API and passing it as props to the Line Component. But only difference is I am using redux here. And obviously, this time the Line Component is not receiving the good data.
The issue might be on this componentDidMount code.
componentDidMount() {
this.props.dispatch(fetchExpenses());
}
As per docs on dispatch
action (Object†): A plain object describing the change that makes
sense for your application. Actions are the only way to get data into
the store, so any data, whether from the UI events, network callbacks,
or other sources such as WebSockets needs to eventually be dispatched
as actions. Actions must have a type field that indicates the type of
action being performed. Types can be defined as constants and imported
from another module. It's better to use strings for type than Symbols
because strings are serializable. Other than type, the structure of an
action object is really up to you. If you're interested, check out
Flux Standard Action for recommendations on how actions could be
constructed.
Here fetchExpenses might be returning a promise and in that case you might need
fetchExpenses().then(apiRes => dipatch({type: "ACTION_TYPE": payload: apiRes}))
Another approach can be to use redux-thunk
Ok I solved this just by checking if the data I was receiving was not null before passing it as props. Which is what I thought this line would do let labels = this.props.months && this.props.months;
<main className="dashboard">
{ this.props.months != null ? <ExpenseChart monthNames={labels}/> : ''; }
</main>
I'm starting with react and trying to set up handsontable in my react app following:
react-handsontable
// import React...
import React from 'react';
import ReactDOM from 'react-dom';
// ... Handsontable with its main dependencies...
import moment from 'moment';
import numbro from 'numbro';
import pikaday from 'pikaday';
import Zeroclipboard from 'zeroclipboard';
import Handsontable from 'handsontable';
// ... and HotTable
import HotTable from 'react-handsontable';
class ExampleComponent extends React.Component {
constructor(props) {
super(props);
this.handsontableData = [
["", "Ford", "Volvo", "Toyota", "Honda"],
["2016", 10, 11, 12, 13],
["2017", 20, 11, 14, 13],
["2018", 30, 15, 12, 13]
];
}
render() {
return (
<div id="example-component">
<HotTable root="hot" data={this.handsontableData} colHeaders={true} rowHeaders={true} width="600" height="300" stretchH="all" />
</div>
);
}
}
Works so far but how do I get the instance of the table like in pure javascript
var ht = new Handsontable(document.getElementById('example1'), options);
ht.setDataAtCell(0, 0, 'new value');
Thanks, Tim
If you're trying to access the core methods, like 'setDataAtCell()', you can use refs to access them.
For example add the "ref='xyz'" attribute to the HTML element and you can then call it with "this.refs.xyz". I've modified your example below to illustrate. It adds a button that onClick runs a function to 'setDataAtCell'.
// import React...
import React from 'react';
import ReactDOM from 'react-dom';
// ... Handsontable with its main dependencies...
import moment from 'moment';
import numbro from 'numbro';
import pikaday from 'pikaday';
import Zeroclipboard from 'zeroclipboard';
import Handsontable from 'handsontable';
// ... and HotTable
import HotTable from 'react-handsontable';
class ExampleComponent extends React.Component {
constructor(props) {
super(props);
this.handsontableData = [
["", "Ford", "Volvo", "Toyota", "Honda"],
["2016", 10, 11, 12, 13],
["2017", 20, 11, 14, 13],
["2018", 30, 15, 12, 13]
];
}
handleClick(e) {
this.refs.hot.hotInstance.setDataAtCell(0, 0, 'new value')
}
render() {
return (
<div id="example-component">
<HotTable root="hot"
data={this.handsontableData}
colHeaders={true}
rowHeaders={true}
width="600"
height="300"
stretchH="all"
ref="hot"
/>
<br/>
<button onClick={(e)=>this.handleClick(e)}>Click Me</button>
</div>
);
}
}
export default ExampleComponent
This method can be used to access other methods like "getData()" which can be used to get a snapshot of the data in the table which can be saved to state or similar. So it's more lengthy than "ht" you can use "this.refs.hot.hotInstance" for similar affect.
You can read more about the ref attribute in "Refs and the DOM" in the React documentation.
To access the instance of HotTable component, use ref. However, don't use old way of using ref. As of version 16.3, React provides 2 ways :
using createRef API which is the recommended way
using callback ref
which is already available in earlier version, but better than the
old "string ref" way.
I only show how to use createRef here :
In your constructor, add the following :
this.refToHotIns=React.createRef();
The name of the field property is arbitrary, you can name it as you like.
In your render() method, change the JSX element to :
<HotTable ref={this.refToHotIns} data={this.handsontableData} colHeaders={true} rowHeaders=true} width="600" height="300" stretchH="all" />
Now, this.refToHotIns.current references to mounted HotTable instance. The Handsontable instance is stored under the hotInstance property of the wrapper component. So you can then access properties/methods of HotTable instance, like so :
this.refToHotIns.current.hotInstance.setDataAtCell(0, 0, 'new value');
It's pretty simple to write your own react wrapper for handsontable, and then you can create a reference to your HOT instance. Here is some sample React component code:
componentWillReceiveProps({ gridSpec }) {
if (gridSpec) {
const {columns, colHeaders, data} = gridSpec;
const container = document.getElementById(GRID_ID);
this.hotInstance = new handsontable(container, {
columns,
colHeaders,
data,
height: 600
});
}
}
shouldComponentUpdate () {
return false;
}
render () {
return (
<div style={{overflowX: 'hidden', height: '600px'}}>
<div id={GRID_ID} />
</div>
)
}
you have your data as an array defined in the constructor.
this.handsonetableData = [[First row],[second row]]
You could simply link that data to a state and setState inside your component. It should be really straightforward.
this.state = {
table: [[first line], [second line]]
}
Eventually going further you can write your own method that update a specific value of that array.
constructor (props) {
super(props)
this.state = {
table: [[first row], [second row]]
}
}
updateValueInTable (row, col, value)
checkIdontDoAnythingStupid()
let newTable = this.state.table
newTable[row][col] = value
this.setState({ table: newTable})
}
If you do not want to use the state and use something like redux you put the logic in the reducer and the triggers in actions. And there you are!
Of course is up to you how to check that you manipulate correctly your array, a lot of libraries can come to help (lodash and co.)