Related
With this code:
import ReactEChartsCore from 'echarts-for-react/lib/core';
// Import the echarts core module, which provides the necessary interfaces for using echarts.
import * as echarts from 'echarts/core';
// import components, all suffixed with Component
import {
GridComponent,
TooltipComponent,
TitleComponent,
DatasetComponent,
} from 'echarts/components';
// Import renderer, note that introducing the CanvasRenderer or SVGRenderer is a required step
import {
CanvasRenderer,
} from 'echarts/renderers';
function App_D() {
const options = {
grid: { top: 8, right: 8, bottom: 24, left: 36, containLabel: true },
xAxis: {
type: 'category',
data: ['Mon', 'Tue', 'Wed', 'Thu', 'Fri', 'Sat', 'Sun'],
},
yAxis: {
type: 'value',
},
series: [
{
data: [820, 932, 901, 934, 1290, 1330, 1320],
type: 'line',
//type: 'bar',
//type: 'radar',
smooth: true,
},
],
tooltip: {
trigger: 'axis',
},
};
return (
<div className='container'>
<h1 className='heading'>
Data & Context Visualization
</h1>
<ReactECharts option={options} />;
</div>
);
}
export default App_D;
I get a correct chart.
But with this code:
echarts.tsx :
import ReactECharts from 'echarts-for-react'
// import the core library.
import ReactEChartsCore from 'echarts-for-react/lib/core';
// Import the echarts core module, which provides the necessary interfaces for using echarts.
import * as echarts from 'echarts/core';
// import components, all suffixed with Component
import {
GridComponent,
TooltipComponent,
TitleComponent,
DatasetComponent,
} from 'echarts/components';
// Import renderer, note that introducing the CanvasRenderer or SVGRenderer is a required step
import {
CanvasRenderer,
} from 'echarts/renderers';
interface Props {
chartType: string;
seriesData: number[];
xAxisType: string;
xAxisData: string[];
}
export default function EchartDeploy({
chartType,
seriesData,
xAxisType,
xAxisData
}: Props) {
React.useEffect(() => {
echarts.use(
[TitleComponent, TooltipComponent, GridComponent, CanvasRenderer]
)
}, [])
const options = {
grid: { top: 8, right: 8, bottom: 24, left: 36, containLabel: true },
aAxis: {
type: xAxisType,
data: xAxisData,
},
yAxis: {
type: 'value',
},
series: [
seriesData,
chartType,
],
tooltip: {
trigger: 'axis',
},
}
return (
<ReactECharts option={options} />
);
}
App_D.tsx :
import EchartDeploy from './dataVisualize/echarts'
function App_D() {
let [chart_type, setChart_type] = React.useState("")
let [series_data, setSeries_data] = React.useState<number[]>([])
let [xAxis_type, setXAxis_type] = React.useState("")
let [xAxis_data, setXAxis_data] = React.useState<string[]>([])
setChart_type('line')
setSeries_data([820, 932, 901, 934, 1290, 1330, 1320])
setXAxis_type('category')
setXAxis_data(['Mon', 'Tue', 'Wed', 'Thu', 'Fri', 'Sat', 'Sun'])
return (
<div className='container'>
<h1 className='heading'>
Data & Context Visualization
</h1>
<EchartDeploy
chartType={chart_type}
seriesData={series_data}
xAxisType={xAxis_type}
xAxisData={xAxis_data}
/>
</div>
);
}
export default App_D;
I get no errors messages anymore, but also no chart.
What am I doing wrongly? How to pass the parameters to the React functional component?
function App_D() {
//here should be defind all of yours useStates() for chart_type/series_data etc.
useEffect(() => {
//all of your setters
}, []); //with an empty dependency array
return (
<div className='container'>
<h1 className='heading'>
Data & Context Visualization
</h1>
<EchartDeploy
chartType={chart_type}
seriesData={series_data}
xAxisType={xAxis_type}
xAxisData={xAxis_data}
/>
</div>
)
I'm trying to add the column definition programmatically,on button click, instead of hardcoding it in my ReactJS page.
{
headerName: "Product1",
resizable: true,
wrapText: true,
cellStyle: {
'white-space': 'normal'
},
autoHeight: true,
hide: true,
cellRendererFramework.MyCustomColumnRenderer
}
Not sure how to go about implementing this?
Thanks for your help.
Use setColumnDefs(columnDefs)
const columnDefs = getColumnDefs();
columnDefs.forEach(function (colDef, index) {
colDef.headerName = 'Abcd';
});
this.gridApi.setColumnDefs(columnDefs);
https://plnkr.co/edit/0ctig4P2yzPjhycB
You could define the columnDefs in the grid to use a state and then set the state dynamically.
import React from 'react';
import { render } from 'react-dom';
import { AgGridColumn, AgGridReact } from 'ag-grid-react';
import 'ag-grid-community/dist/styles/ag-grid.css';
import 'ag-grid-community/dist/styles/ag-theme-alpine.css';
const App = () => {
const rowData = [
{ make: 'Toyota', model: 'Celica', price: 35000 },
{ make: 'Ford', model: 'Mondeo', price: 32000 },
{ make: 'Porsche', model: 'Boxter', price: 72000 },
];
// use the colDefs state to define the column definitions
const [colDefs, setColDefs] = React.useState([{ field: 'make' }]);
// when the button is pressed set the state to cause the grid to update
const handleAddColumns = ()=> {
const dynamicFields = [
{ field: 'make', header: 'Car Make' },
{ field: 'model', sortable: true },
{ field: 'price' },
];
setColDefs(dynamicFields);
}
return (
<div>
<button onClick={handleAddColumns}>Add Column Defs</button>
<div className="ag-theme-alpine" style={{ height: 400, width: 600 }}>
<AgGridReact
rowData={rowData}
columnDefs={colDefs}>
</AgGridReact>
</div>
</div>
);
};
render(<App />, document.getElementById('root'));
Another approach is to use the Api's setColumnDef method:
import React from 'react';
import { render } from 'react-dom';
import { AgGridColumn, AgGridReact } from 'ag-grid-react';
import 'ag-grid-community/dist/styles/ag-grid.css';
import 'ag-grid-community/dist/styles/ag-theme-alpine.css';
const App = () => {
const rowData = [
{ make: 'Toyota', model: 'Celica', price: 35000 },
{ make: 'Ford', model: 'Mondeo', price: 32000 },
{ make: 'Porsche', model: 'Boxter', price: 72000 },
];
// using state to define the columns initially
const [colDefs, setColDefs] = React.useState([{ field: 'make' }]);
// get a reference to the API when the onGridReady is fired
// see the Grid definition in the JSX
const [gridApi, setGridApi] = React.useState([]);
const handleAddColumns = ()=> {
const dynamicFields = [
{ field: 'make', header: 'Car Make' },
{ field: 'model', sortable: true },
{ field: 'price' },
];
// use the API to set the Column Defs
gridApi.setColumnDefs(dynamicFields);
}
return (
<div>
<button onClick={handleAddColumns}>Add Column Defs</button>
<div className="ag-theme-alpine" style={{ height: 400, width: 600 }}>
<AgGridReact
rowData={rowData}
columnDefs={colDefs}
onGridReady={ params => {setGridApi(params.api)} }
></AgGridReact>
</div>
</div>
);
};
render(<App />, document.getElementById('root'));
The examples in the documentation should help:
https://www.ag-grid.com/react-data-grid/column-definitions/
https://www.ag-grid.com/react-data-grid/column-updating-definitions/
There is also a blog post from AG Grid that covers dynamic column definitions:
https://blog.ag-grid.com/binding-and-updating-column-definitions-in-ag-grid/
I can't figure out how to implement a simple search bar to the ag-grid i set. I would like to let my input filter the results in my grid based on every columns I couldn't figure out a good documentation with example for that. Here is my code. Feel free to redirect me to a proper example or another question similar.
import React from 'react';
import { AgGridReact } from 'ag-grid-react';
import axios from 'axios';
import 'ag-grid-community/dist/styles/ag-grid.css';
import 'ag-grid-community/dist/styles/ag-theme-alpine.css';
class ListTableClients extends React.Component {
constructor(props) {
super(props);
this.state = {
defaultColDef: {
flex: 1,
cellClass: 'cell-wrap-text',
autoHeight: true,
sortable: true,
resizable: true,
},
columnDefs: [
{ headerName: "id", field: "id", maxWidth: 100 },
{ headerName: "name", field: "name"},
{ headerName: "email", field: "email"}],
rowData: [
{ id: 1, name: 'maison du café', email: 'maisonducafe#gamil.com' },
{ id: 2, name: 'Warehouse', email: 'contact#warehouse.fr' },
{ id: 3, name: 'Maestro', email: 'maestro#gmail.com' }],
rowHeight: 275,
}
}
componentDidMount() {
console.log('test');
axios.get('http://localhost:8080/listClients').then((res) => {
this.setState({ rowData: res.data });
}).catch((error) => { console.log(error) });
}
render() {
return (
<div style={{width: '100%', paddingLeft: '50px', paddingRight: '50px', paddingTop: '50px'}} className="ag-theme-alpine">
<input type="text" placeholder="Filter..." onInput={this.onFilterTextBoxChanged}/>
<AgGridReact
domLayout='autoHeight'
columnDefs={this.state.columnDefs}
defaultColDef={this.state.defaultColDef}
getRowHeight={this.state.getRowHeight}
rowData={this.state.rowData}>
</AgGridReact>
</div>
);
}
}
export default ListTableClients;
Refer this demo
If the cell data in object format then you have to format it Ag-Grid Value Formatters
I'm working on separating code from index.tsx into two different files viz: firstTab.tsx and secondTab.tsx. I haven't started working on secondTab.tsx yet.
I separated first tab related code into firstTab.tsx as shown in the following code editor: The full functional code with both tabs working are in index.tsx is pasted below:
import React, { Component } from "react";
import { render } from "react-dom";
import "jqwidgets-scripts/jqwidgets/styles/jqx.base.css";
import JqxButton from "jqwidgets-scripts/jqwidgets-react-tsx/jqxbuttons";
import * as ReactDOM from "react-dom";
import JqxWindow from "jqwidgets-scripts/jqwidgets-react-tsx/jqxwindow";
import JqxInput from "jqwidgets-scripts/jqwidgets-react-tsx/jqxinput";
import JqxChart, {
IChartProps
} from "jqwidgets-scripts/jqwidgets-react-tsx/jqxchart";
import JqxGrid, {
IGridProps,
jqx
} from "jqwidgets-scripts/jqwidgets-react-tsx/jqxgrid";
import JqxTabs from "jqwidgets-scripts/jqwidgets-react-tsx/jqxtabs";
import JqxDropDownList, {
IDropDownListProps
} from "jqwidgets-scripts/jqwidgets-react-tsx/jqxdropdownlist";
import firstTab from './firstTab';
interface AppProps {}
interface AppState {
name: string;
}
interface IProps extends IGridProps {
dropdownlistSource: IDropDownListProps["source"];
}
class App extends Component<{}, IProps> {
private myTabs = React.createRef<JqxTabs>();
private gridElement = React.createRef<HTMLDivElement>();
private myGrid = React.createRef<JqxGrid>();
private gridElementTwo = React.createRef<HTMLDivElement>();
private myGrid2 = React.createRef<JqxGrid>();
constructor(props: {}) {
super(props);
this.state = {
dropdownlistSource: [
{ value: 0, label: "Affogato" },
{ value: 1, label: "Americano" },
{ value: 2, label: "Bicerin" },
{ value: 3, label: "Breve" }
]
};
}
public render() {
return (
<JqxTabs
ref={this.myTabs}
// #ts-ignore
width={400}
height={560}
initTabContent={this.initWidgets}
>
<ul>
<li style={{ marginLeft: 30 }}>
<div style={{ height: 20, marginTop: 5 }}>
<div
style={{
marginLeft: 4,
verticalAlign: "middle",
textAlign: "center",
float: "left"
}}
>
US Indexes
</div>
</div>
</li>
<li>
<div style={{ height: 20, marginTop: 5 }}>
<div
style={{
marginLeft: 4,
verticalAlign: "middle",
textAlign: "center",
float: "left"
}}
>
NASDAQ compared to S&P 500
</div>
</div>
</li>
</ul>
<div style={{ overflow: "hidden" }}>
<div id="jqxGrid" ref={this.gridElement} />
<div style={{ marginTop: 10, height: "15%" }} />
</div>
<div style={{ overflow: "hidden" }}>
<div id="jqxGrid2" ref={this.gridElementTwo} />
<div style={{ marginTop: 10, height: "15%" }} />
</div>
</JqxTabs>
);
}
private initGrid = () => {
const source = {
datafields: [{ name: "Date" }, { name: "S&P 500" }, { name: "NASDAQ" }],
datatype: "csv",
localdata: `1/2/2014,1831.98,4143.07
1/3/2014,1831.37,4131.91
1/6/2014,1826.77,4113.68
1/7/2014,1837.88,4153.18
1/8/2014,1837.49,4165.61
1/9/2014,1838.13,4156.19
2/6/2014,1773.43,4057.12
2/7/2014,1797.02,4125.86`
};
const dataAdapter = new jqx.dataAdapter(source, {
async: false,
loadError: (xhr: any, status: any, error: any) => {
console.log(xhr, status, error);
}
});
const columns: IGridProps["columns"] = [
{ cellsformat: "d", datafield: "Date", text: "Date", width: 250 },
{ datafield: "S&P 500", text: "S&P 500", width: 150 },
{ datafield: "NASDAQ", text: "NASDAQ" }
];
const grid = (
<JqxGrid
ref={this.myGrid}
width={"100%"}
height={400}
source={dataAdapter}
columns={columns}
/>
);
render(grid, this.gridElement.current!);
};
private initGrid2 = () => {
const source = {
datafields: [{ name: "Date" }, { name: "S&P 500" }, { name: "NASDAQ" }],
datatype: "csv",
localdata: `1/2/2014,1831.98,4143.07
1/3/2014,1831.37,4131.91
1/6/2014,1826.77,4113.68
1/7/2014,1837.88,4153.18
1/8/2014,1837.49,4165.61
1/9/2014,1838.13,4156.19
1/10/2014,1842.37,4174.67
2/7/2014,1797.02,4125.86`
};
const dataAdapter = new jqx.dataAdapter(source, {
async: false,
loadError: (xhr: any, status: any, error: any) => {
console.log(xhr, status, error);
}
});
const columns: IGridProps["columns"] = [
{ cellsformat: "d", datafield: "Date", text: "Date", width: 250 },
{ datafield: "S&P 500", text: "S&P 500", width: 150 },
{ datafield: "NASDAQ", text: "NASDAQ" }
];
const grid = (
<JqxGrid
ref={this.myGrid2}
width={"100%"}
height={400}
source={dataAdapter}
columns={columns}
/>
);
render(grid, this.gridElementTwo.current!);
};
private initWidgets = (tab: any) => {
switch (tab) {
case 0:
this.initGrid();
break;
case 1:
this.initGrid2();
break;
}
};
}
render(<App />, document.getElementById("root"));
Question:
Since I've already moved private initGrid = () => { inside a separate file firstTab.tsx, in index.tsx where should I put {firstTab.tsx} to make sure both tabs in index.tsx works fine? I mean, even if I comment out private initGrid = () => { function from index.tsx both tabs should work fine.
Thanks
If I would refactor this I would consider the next approach:
Create Parent component Table (probably some more appropriate name)
Create a component for US Indexes
Create a component for NASDAQ compared to S&P 500
Based on the active tab render the proper component.
You could also create a separate file that contains only exports with your data.
If you then import that into your files with the functions you can use that there, keeps it cleaner.
And if you pass that data as a prop / param to your initGrid() functions, you don't have to repeat that code, can reuse it.
I am trying to use use Cytoscape with ReactJS and some how nothing is getting displayed in the simple component i am trying.
Here is the code. I am returning an empty object in mapStateToProps as i am trying to display a static graph where i have hard coded the edges and nodes.
Cytoscape version i am using is from my package.json
"cytoscape": "^2.7.6",
"react": "^15.2.1",
Here is the Cyctoscape jsbin i am using for my sample.
enter link description here
Appreciate any help.
Thanks
import React,{Component} from 'react';
import cytoscape from 'cytoscape';
import {connect} from 'react-redux';
import { bindActionCreators } from 'redux';
class GraphContainer extends React.Component{
constructor(props){
super(props);
this.renderCytoscapeElement = this.renderCytoscapeElement.bind(this);
}
renderCytoscapeElement(){
console.log('* Cytoscape.js is rendering the graph..');
this.cy = cytoscape(
{
container: document.getElementById('cy'),
boxSelectionEnabled: false,
autounselectify: true,
style: cytoscape.stylesheet()
.selector('node')
.css({
'height': 80,
'width': 80,
'background-fit': 'cover',
'border-color': '#000',
'border-width': 3,
'border-opacity': 0.5,
'content': 'data(name)',
'text-valign': 'center',
})
.selector('edge')
.css({
'width': 6,
'target-arrow-shape': 'triangle',
'line-color': '#ffaaaa',
'target-arrow-color': '#ffaaaa',
'curve-style': 'bezier'
})
,
elements: {
nodes: [
{ data: { id: 'cat' } },
{ data: { id: 'bird' } },
{ data: { id: 'ladybug' } },
{ data: { id: 'aphid' } },
{ data: { id: 'rose' } },
{ data: { id: 'grasshopper' } },
{ data: { id: 'plant' } },
{ data: { id: 'wheat' } }
],
edges: [
{ data: { source: 'cat', target: 'bird' } },
{ data: { source: 'bird', target: 'ladybug' } },
{ data: { source: 'bird', target: 'grasshopper' } },
{ data: { source: 'grasshopper', target: 'plant' } },
{ data: { source: 'grasshopper', target: 'wheat' } },
{ data: { source: 'ladybug', target: 'aphid' } },
{ data: { source: 'aphid', target: 'rose' } }
]
},
layout: {
name: 'breadthfirst',
directed: true,
padding: 10
}
});
}
componentDidMount(){
this.renderCytoscapeElement();
}
render(){
return(
<div className="node_selected">
<div style="{height:'400px';width:'400px'}" id="cy"/>
</div>
)
}
}
function mapStateToProps(state){
return {};
}
export default connect(mapStateToProps,null)(GraphContainer);
For those still looking for how to get the code posted working - I was able to get it working by modifying the cy div, specifying its style with non-zero height and width.
render() {
let cyStyle = {
height: '1000px',
width: '1000px',
margin: '20px 0px'
};
return (
<div>
<div style={cyStyle} id="cy"/>
</div>
);
}
I had to integrate cytoscape.js with react as well, but no redux, so wrote a gist in case anybody else needs it.
code example
I am able to resolve the Issue. I missed the Styles for the Layer itself and hence it is defaulting to 0px height and 0px width.
Thanks
For a basic version of the above using the cytoscape "Getting Started" example and using React hooks you can do this:
import React, {Fragment, useEffect, useRef} from 'react';
import cytoscape from 'cytoscape'
const GraphTest = () => {
const graphRef = useRef(null)
const drawGraph = () => {
const cy = cytoscape({
container: graphRef.current,
elements: [
{ data: { id: 'a' } },
{ data: { id: 'b' } },
{
data: {
id: 'ab',
source: 'a',
target: 'b'
}
}]
})
}
useEffect(() => {
drawGraph()
}, [])
return (
<Fragment>
<h2>Graph Test</h2>
<div ref={graphRef} style={{width: '100%', height: '80vh'}}>
</div>
</Fragment>
)
}
export default GraphTest