React : Ag Grid Pagination Server Side - reactjs

I am using AG-Grid library for my work in React JS.
I have 40000 data which I want to show using pagination (not scroll but page1, page2 , page3 and so on...).
I am totally new to it . I have used below link for reference. but it's not working.
Any one has working example ?
AG Grid Sever Side Pagination
Any help would be great.
Thank You.

"use strict";
import React, { Component } from "react";
import { render } from "react-dom";
import { AgGridReact } from "#ag-grid-community/react";
import { AllModules } from "#ag-grid-enterprise/all-modules";
import "#ag-grid-community/all-modules/dist/styles/ag-grid.css";
import "#ag-grid-community/all-modules/dist/styles/ag-theme-balham-dark.css";
class GridExample extends Component {
constructor(props) {
super(props);
this.state = {
modules: AllModules,
columnDefs: [
{ field: "id" },
{
field: "athlete",
width: 150
},
{ field: "age" },
{ field: "country" },
{ field: "year" },
{ field: "sport" },
{ field: "gold" },
{ field: "silver" },
{ field: "bronze" }
],
defaultColDef: {
width: 120,
resizable: true
},
rowModelType: "serverSide",
cacheBlockSize: 100,
maxBlocksInCache: 10
};
}
onGridReady = params => {
this.gridApi = params.api;
this.gridColumnApi = params.columnApi;
const httpRequest = new XMLHttpRequest();
const updateData = data => {
var idSequence = 0;
data.forEach(function(item) {
item.id = idSequence++;
});
var server = new FakeServer(data);
var datasource = new ServerSideDatasource(server);
params.api.setServerSideDatasource(datasource);
};
httpRequest.open(
"GET",
"https://raw.githubusercontent.com/ag-grid/ag-grid/master/packages/ag-grid-docs/src/olympicWinners.json"
);
httpRequest.send();
httpRequest.onreadystatechange = () => {
if (httpRequest.readyState === 4 && httpRequest.status === 200) {
updateData(JSON.parse(httpRequest.responseText));
}
};
};
render() {
return (
<div style={{ width: "100%", height: "100%" }}>
<div style={{ height: "100%", paddingTop: "26px", boxSizing: "border-box" }}>
<div
id="myGrid"
style={{
height: "100%",
width: "100%"
}}
className="ag-theme-balham-dark"
>
<AgGridReact
modules={this.state.modules}
columnDefs={this.state.columnDefs}
defaultColDef={this.state.defaultColDef}
rowModelType={this.state.rowModelType}
cacheBlockSize={this.state.cacheBlockSize}
maxBlocksInCache={this.state.maxBlocksInCache}
animateRows={true}
pagination={true}
onGridReady={this.onGridReady}
/>
</div>
</div>
</div>
);
}
}
function ServerSideDatasource(server) {
return {
getRows: function(params) {
setTimeout(function() {
var response = server.getResponse(params.request);
if (response.success) {
params.successCallback(response.rows, response.lastRow);
} else {
params.failCallback();
}
}, 500);
}
};
}
function FakeServer(allData) {
return {
getResponse: function(request) {
console.log("asking for rows: " + request.startRow + " to " + request.endRow);
var rowsThisPage = allData.slice(request.startRow, request.endRow);
var lastRow = allData.length <= request.endRow ? data.length : -1;
return {
success: true,
rows: rowsThisPage,
lastRow: lastRow
};
}
};
}
Try this lines of react code which is mention in documentation. If it will not work, for more precise answer please share your implemented code.

Related

Rfresh the parents component while updating in detailCellRendering in ag-grid

We have One parents componet Template in That i m using one detailsCellRendering componet for cellRedering in ag-grid..in the detailsCellRendering componet I am updating TextValue and after clicking on handleDoneValue event (done button ) the Template page should also refresh.But I am not able to do ...i need help like how can i update Template page while updating in DetailsCellRending Component.
class Template extends Component {
constructor(props) {
super(props);
this.state = {
columnDefs: [
{
headerName: "Channel Field",
field: "field",
filter: "agTextColumnFilter",
filterParams: {
buttons: ["reset"],
debounceMs: 1000,
suppressAndOrCondition: true, // it will remove AND/OR conditions
filterOptions: [
"contains",
"notContains",
"equals",
"notEqual",
"startsWith",
"endsWith"
]
},
cellRendererParams: {
prop1: "this is prop1"
},
cellRenderer: "agGroupCellRenderer",
},
{
headerName: "Mapping from Your Data",
field: "mapping_field",
filter: "agNumberColumnFilter",
},
{
headerName: skuValue,
field: "value",
},
{
headerName: "Status",
field: "status",
filter: 'agSetColumnFilter',
filterParams: {
values: function (params) {
// simulating async delay
setTimeout(function () {
params.success(["True", "False"]);
}, 500);
}
},
// cellRenderer: "ColourRender",
cellStyle: params => {
if (params.value === "Mapped") {
//mark mapped cells as green
return { color: 'green' };
} else {
return { color: 'red' };
}
}
},
{
headerName: "Required",
field: "required",
filter: "agSetColumnFilter",
cellRenderer: "BooleanRender",
filterParams: {
values: function (params) {
// simulating async delay
setTimeout(function () {
params.success(["True", "False"]);
}, 500);
}
}
},
],
columnDefsforSku: [
{
headerName: "Channel Field",
field: "field",
filter: "agTextColumnFilter",
filterParams: {
buttons: ["reset"],
debounceMs: 1000,
suppressAndOrCondition: true, // it will remove AND/OR conditions
filterOptions: [
"contains",
"notContains",
"equals",
"notEqual",
"startsWith",
"endsWith",
// "In List",
// "Not In List"
]
},
cellRenderer: "agGroupCellRenderer",
},
{
headerName: "Mapping from Your Data",
field: "mapping_field",
filter: "agNumberColumnFilter",
},
{
headerName: "Status",
field: "status",
filter: 'agSetColumnFilter',
filterParams: {
values: function (params) {
// simulating async delay
setTimeout(function () {
params.success(["True", "False"]);
}, 500);
}
},
cellStyle: params => {
if (params.value === "Mapped") {
//mark mapped cells as green
return { color: 'green' };
} else {
return { color: 'red' };
}
}
},
{
headerName: "Required",
field: "required",
filter: "agSetColumnFilter",
cellRenderer: "BooleanRender",
filterParams: {
values: function (params) {
// simulating async delay
setTimeout(function () {
params.success(["True", "False"]);
}, 500);
}
}
},
],
components: {
DetailCellRenderer: {DetailCellRenderer},
},
defaultColDef: {
flex: 1,
resizable: true,
// tooltipComponent: "customTooltip",
floatingFilter: true,
minWidth: 170,
sortable: true,
},
rowModelType: "serverSide",
frameworkComponents: {
customNoRowsOverlay: CustomNoRowsOverlay,
loadingRender: loadingRender,
myDetailCellRenderer: DetailCellRenderer,
customTooltip: CustomTooltip,
BooleanRender: BooleanRender,
// ColourRender: ColourRender,
},
context: { componentParent: this },
pagination: true,
serverSideStoreType: "full",
rowSelection: "multiple",
loadingCellRenderer: "loadingRender",
loadingCellRendererParams: { loadingMessage: "One moment please..." },
loadingOverlayComponent: "loadingRender",
totalProductsCount: 0,
catalogfilterCount: 0,
noRowsOverlayComponent: "customNoRowsOverlay",
noRowsOverlayComponentParams: {
noRowsMessageFunc: function () {
return "Please Select Product Preview"
}
},
getDetailRowData: function (params) {
// params.successCallback([]);
params.successCallback(params.data.callRecords);
},
sideBar: 'filters',
tooltipShowDelay: 0,
paginationPageSize: 100,
cacheBlockSize: 30,
filterStatus: false,
sweetAlert: "",
allSKu: [],
sku: localStorage.getItem("skuPreviewProduct"),
isProductPrevewSelected: false,
skuInputValue: "",
loading: false,
product_id: localStorage.getItem("products_ids") ? localStorage.getItem("products_ids") : null,
// loadingForDetails: localStorage.getItem("loadings")
};
<Grid item xs={10}>
<div
id="myGrid"
style={{
height: "90%",
width: "90%",
}}
className="ag-theme-alpine template"
>
<AgGridReact
columnDefs={this.state.product_id ? columnDefs : columnDefsforSku}
defaultColDef={defaultColDef}
onGridReady={this.onGridReady}
rowModelType={rowModelType}
masterDetail={true}
enableCellChangeFlash={true}
masterDetail={true}
detailCellRenderer={'myDetailCellRenderer'}
detailRowHeight={350}
height={400}
width={600}
animateRows={true}
frameworkComponents={frameworkComponents}
embedFullWidthRows={true}
loadingOverlayComponent={loadingOverlayComponent}
loadingCellRenderer={loadingCellRenderer} // default loading renderer
loadingCellRendererParams={loadingCellRendererParams} // renderer Params to load msg
noRowsOverlayComponent={noRowsOverlayComponent} // default no rows overlay component
noRowsOverlayComponentParams={noRowsOverlayComponentParams} // to show default no rows message
paginationPageSize={this.state.paginationPageSize} // pagination page size
onColumnVisible={this.onColumnVisible.bind(this)}
getDetailRowData={getDetailRowData}
cacheBlockSize={cacheBlockSize}
detailCellRendererParams={detailCellRendererParams }
/>
</div>
</Grid>
</Grid>
</div>
)
1. **List item**
}
// DetailsCellRendering page
import React, { useEffect, useState } from 'react';
import Paper from '#material-ui/core/Paper';
import Grid from '#material-ui/core/Grid';
import { makeStyles } from '#material-ui/core/styles';
import TemplateTab from "../views/FunctionalComponents/TemplateTab"
import { TEMPLATE_MARKETPLACE_FEILD_MAPPING, TEMPLATE_API } from "../configurations/configApi";
import { apiEdit, fetchUrl } from "../apiActions/action";
import LoadingOverlay from "../components/overlays/LoadingOverlay";
import Templates from 'views/Tables/Templates';
// import Template from 'views/Tables/Templates';
const useStyles = makeStyles(() => ({
root: {
flexGrow: 1,
textAlign: "center",
marginBottom: 20,
}
}));
const DetailCellRenderer = ({ data, params, api, node}) => {
const classes = useStyles();
const [allData, setAllData] = useState();
const [loading, setLoading] = useState(false);
const marketplaceId = localStorage.getItem("marketplaceId") ? localStorage.getItem("marketplaceId") : "" ;
const skuValue = localStorage.getItem("skuPreviewProduct") ? localStorage.getItem("skuPreviewProduct") : "";
const fetchAllTemplate = () => {
setLoading(true);
var soniServe = `${TEMPLATE_API}${marketplaceId}/?sku=${skuValue}&filter=${"[]"}`;
fetchUrl(soniServe, ({ status, response }) => {
if (status) {
let refreshValue = response.data.response[0].mappings.filter(item => data.id === item.id);
localStorage.setItem("cellRenderId", refreshValue && refreshValue[0]&& refreshValue[0].id )
setAllData(refreshValue && refreshValue[0])
setLoading(false)
} else {
if (response.response &&
response.response.status &&
((response.response.status === 401))
) {
localStorage.removeItem("token");
localStorage.removeItem("email");
window.location = "/auth/login-page";
}
}
});
}
useEffect(() => {
setAllData(data)
}, data)
// update text value
const handleDoneValue = (textValue) => {
const productId = allData && allData.id;
let value = textValue
// updating the existing labels
const urlForSave = `${TEMPLATE_MARKETPLACE_FEILD_MAPPING}${productId}/`;
const methodOfSave = "put";
const data = { "mappings": { "text_value": value } }
apiEdit(urlForSave, data, methodOfSave, ({ status, response }) => {
if (status) {
// window.location = `/configuration/details/${marketplaceId}`
fetchAllTemplate();
// inputMethod === "saveAs" && this.fetchProductDisplay("saveAs");
} else {
if (response.response &&
response.response.status &&
((response.response.status === 401))
) {
localStorage.removeItem("token");
localStorage.removeItem("email");
window.location = "/auth/login-page";
} else if (
(response &&
response.status &&
(response.status === 404 ||
response.status === 500)) ||
!response
) {
window.location = "/error";
} else {
// to show some popups
window.location = "/error";
}
}
});
}
return (
<div>
<div className={classes.root}>
<Grid container style={{ paddingTop: "10px" }}>
<Grid item xs={3}>
{allData && allData.field ? allData.field : null}
</Grid>
<Grid item xs={3}>
{ allData && allData.mapping_field ? allData.mapping_field : null}
</Grid>
<Grid item xs={3}>
{urlCheck && urlCheck[0] === "https" || urlCheck && urlCheck[0] === "http"? {allData && allData.value} : allData && allData.value ? allData.value : null}
{/* { data && data.value ? data.value : null} */}
</Grid>
<Grid item xs={3} >
{allData && allData.status}
</Grid>
</Grid>
</div>
<div className={classes.root}>
<Grid container spacing={1}>
<Grid item xs={4} justify="flex-end" style={{ display: "flex" }}>
Description
</Grid>
<Grid item xs={8} >
<Paper className="templateBox">
<span style={{ marginBottom: "20px" }}>What value should we send for each product's "{data.field}"? </span>
<TemplateTab allCellData={data} handleDoneValue={handleDoneValue}
/>
</Paper>
</Grid>
</Grid>
</div>
<LoadingOverlay showOverlay={loading} />
</div>
);
};
export default DetailCellRenderer;

Unable to do Server-Side Sorting with ag-grid in react-redux

I'm trying to call redux action and to pass inside the sortModel in order to get the sorted data from the server.
[Example from documentation] (https://www.ag-grid.com/javascript-grid-server-side-model-sorting)
Can somebody help me to understand what I'm doing wrong?
...
defaultColDef: {
sortable: true,
flex: 1,
minWidth: 100,
resizable: true,
},
rowModelType: 'serverSide',
};
}
serverSideDatasource(response) {
return {
getRows: function(params) {
console.log('[Datasource] - rows requested by grid: ', params.request);
//Redux action
this.props.getSortedDataFromServer( params.request.sortModel);
setTimeout(function() {
if (response.success) {
params.successCallback(response.rows, response.lastRow);
} else {
params.failCallback();
}
}, 500);
},
};
}
onGridReady = params => {
//Data from redux store
const { result } = this.props.sortedData;
this.gridApi = params.api;
this.gridColumnApi = params.columnApi;
var datasource = this.serverSideDatasource(result);
params.api.setServerSideDatasource(datasource);
};
render() {
return (
<div style={{ width: '100%', height: '100%' }}>
<div
id="myGrid"
style={{
height: '100%',
width: '100%',
}}
className="ag-theme-alpine-dark"
>
<AgGridReact
columnDefs={this.state.columnDefs}
defaultColDef={this.state.defaultColDef}
rowModelType={this.state.rowModelType}
animateRows={true}
onGridReady={this.onGridReady}
/>
</div>
</div>
);
}
}
...

breaking big component into smaller one

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.

ComponentDidUpdate causing infinite render even when wrapped in condition

I'm trying to pull some data from Google Analytics reporting API and display the data inside the apex charts library. I managed to successfully do this. However, I now want filtering options to where if the user selects a certain date within the date range picker react wrapper, the apex charts data gets updated from the API.
I'm struggling figuring out on how when my data gets updated, to update the state with the new state within my life cycle method? I think I'm doing something minor I just don't know what it is. I looked up the documentation on the life cycle method and it says to make sure to wrap it inside a condition which I did. However, when the else condition is met, it causes an infinite render.
Here is my code: (the bug i'm stuck on is the componentWillUpdate lifecycle method) everything else works fine.
import React from "react";
import Header from "../common/Header";
import Footer from "../common/Footer";
import moment from "moment";
import $ from "jquery";
import ApexCharts from "apexcharts";
import Chart from "react-apexcharts";
import DateRangePicker from "react-bootstrap-daterangepicker";
const VIEW_ID = "";
class Charts extends React.Component {
constructor(props) {
super(props);
this.printResults = this.printResults.bind(this);
this.pageViews = this.pageViews.bind(this);
this.handleError = this.handleError.bind(this);
this.state = {
loading: true,
filterstartDate: "",
filterendDate: "",
// Start Series Bar State
ChartOne: {
chart: {
id: "ChartOne"
},
colors: ["#e31d1a"],
xaxis: {
categories: [],
labels: {
style: {
colors: []
}
},
title: {
text: "Locations"
}
},
yaxis: {
labels: {
style: {
colors: []
}
},
title: {
text: "Count"
}
}
},
ChartOneSeries: [],
}
pageViews = async () => {
window.gapi.client
.request({
path: "/v4/reports:batchGet",
root: "https://analyticsreporting.googleapis.com",
method: "POST",
body: {
reportRequests: [
{
viewId: VIEW_ID,
dateRanges: [
{
startDate: "7daysAgo",
endDate: "today"
}
],
metrics: [
{
expression: "ga:pageviews"
}
],
dimensions: [
{
name: "ga:country"
}
],
orderBys: [{ fieldName: "ga:pageviews", sortOrder: "DESCENDING" }]
}
]
}
})
.then(this.printResults, this.handleError);
};
componentDidMount() {
$.getScript("https://apis.google.com/js/client:platform.js").done(() => {
window.gapi.signin2.render("my-signin2", {
scope: "profile email",
width: 240,
height: 50,
longtitle: true,
theme: "dark",
onsuccess: this.pageViews,
onfailure: this.handleError
});
});
}
//log the data
printResults(response) {
let pageviewLocation = [];
let pageviewCount = [];
let pageviewTotal = response.result.reports[0].data.totals[0].values[0];
let totalComma = pageviewTotal
.toString()
.replace(/\B(?=(\d{3})+(?!\d))/g, ",");
response.result.reports[0].data.rows.map(value => {
//console.log(value.dimensions);
pageviewLocation.push(value.dimensions[0]);
pageviewCount.push(parseInt(value.metrics[0].values[0]));
});
//console.log(total);
this.setState({
loading: false,
ChartOne: {
title: {
text: totalComma,
align: "center",
style: {
fontSize: "20px"
}
},
subtitle: {
text: "Total Page Views",
align: "center",
style: {
fontSize: "14px",
cssClass: "apexcharts-yaxis-title"
}
},
plotOptions: {},
...this.state.ChartOne,
xaxis: {
width: 1,
...this.state.ChartOne.xaxis,
labels: {
show: false,
...this.state.ChartOne.xaxis.labels,
style: {
...this.state.ChartOne.xaxis.labels.style
}
},
categories: pageviewLocation
},
yaxis: {
min: 0,
...this.state.ChartOne.yaxis,
labels: {
//show: false,
...this.state.ChartOne.yaxis.labels,
style: {
...this.state.ChartOne.yaxis.labels.style
}
}
}
},
ChartOneSeries: [
{
name: "Total Page Views",
data: pageviewCount
}
]
});
}
componentDidUpdate(prevProps, prevState) {
if (this.state.filterstartDate === "" && this.state.filterendDate === "") {
console.log("they are empty");
} else {
this.setState({
// this fails immediately once the condition is met
test: "success!"
});
}
}
Datepicker = async (event, picker) => {
this.setState({
filterstartDate: moment(picker.startDate._d).format("YYYY-MM-DD"),
filterendDate: moment(picker.endDate._d).format("YYYY-MM-DD")
});
//console.log(this.state);
};
//or the error if there is one
handleError(reason) {
console.error(reason);
console.error(reason.result.error.message);
}
render() {
//console.log();
return (
<div className="containerfluid" id="fullWidth">
<Header />
<div className="container" id="chartContainer">
<h1>Site Analytics</h1>
<div className="row">
<div className="col-md-12">
<DateRangePicker
startDate={moment().format("MM-DD-YYYY")}
endDate={moment().format("MM-DD-YYYY")}
onApply={this.Datepicker}
>
<button className="btn btn-info">
<i className="fas fa-filter">
<span
style={{
fontFamily: "Roboto, san-serif",
fontWeight: "normal",
padding: "5px"
}}
>
Filter Date
</span>
</i>
</button>
</DateRangePicker>
</div>
</div>
<div className="row">
<div className="col-md-4">
{/* Chart One Line */}
{this.state.loading ? (
<React.Fragment>
<i className="fas fa-spinner fa-3x" id="loader" /> Please wait
...!
</React.Fragment>
) : (
<div className="chartContainer">
<Chart
options={this.state.ChartOne}
series={this.state.ChartOneSeries}
type="line"
width={400}
height={300}
/>
</div>
)}
</div>
</div>
<div id="my-signin2" />
</div>
<Footer />
</div>
);
}
}
export default Charts;
When you use setState you're triggering the lifecycle again. If you don't set your filterstartDate and filterendDate to "", you'll keep calling setState infinitely.
componentDidUpdate(prevProps, prevState) {
if (this.state.filterstartDate === "" && this.state.filterendDate === "") {
console.log("they are empty");
} else {
this.setState({
filterstartDate: "",
filterendDate: "",
test: "success!"
});
}
}

Cytoscape and ReactJS integration

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

Resources