Hi,
I am trying to get this grid to display the TEST message in the detail when I click the expander against the row. Everything looks to be working as expected (I am using state.fetchErrorMsg to provide debug text to prove that state is changing and triggering re-rendering when necessary, I can also confirm that the expander toggles between + and - as expected).
Any ideas what I am doing wrong here? I suspect it is something to do with how I am handling the promise that returns the data, since I can get this working when I use locally built static arrays instead of the fetch.
Cheers
Mike
import React, { useEffect, useState } from 'react';
import { UserInfo, TcbObjMilestoneGrp, TcbObjInfo } from '../../models/models';
import { loadingDiv } from '../../functions/componentFunctions';
import { Grid, GridColumn, GridExpandChangeEvent, GridDetailRowProps } from '@progress/kendo-react-grid';
import './TcbObjMilestones.css';
type TcbObjMilestonesProps = {
tcbObj: TcbObjInfo;
userInf: UserInfo;
}
type TcbObjMilestonesState = {
milestoneList: TcbObjMilestoneGrp[];
milestonesFetched: boolean;
fetchError: boolean;
fetchErrorMsg: string;
fetchInProg: boolean;
}
function TcbObjMilestones(props: TcbObjMilestonesProps) {
const [state, setState] = useState<TcbObjMilestonesState>({
milestoneList: [],
milestonesFetched: false,
fetchError: false,
fetchErrorMsg: '',
fetchInProg: false
});
useEffect(() => {
state.fetchErrorMsg = 'FetchInProg';
state.fetchInProg = true;
setState({ ...state});
let url = props.userInf.currProject.apiUrl + '/api/details/GetTcbObjMilestones';
fetch(url, { method: 'POST', body: JSON.stringify(props.tcbObj), headers: { 'Content-Type': 'application/json', 'Authorization': 'Bearer ' + props.userInf.token } })
.then(resp => resp.json())
.then(res => {
switch (res.callStatus) {
case "OK":
let ml: Array<TcbObjMilestoneGrp> = res.results;
state.fetchErrorMsg = 'Got MilestoneData '
state.milestoneList = ml;
state.milestonesFetched = true;
state.fetchInProg = false;
setState({ ...state });
break;
case "UNAUTH":
let uInf: UserInfo = { ...props.userInf, isAuthorised: false };
state.fetchInProg = false;
setState({ ...state });
break;
default:
state.fetchInProg = false;
state.fetchError = true;
state.fetchErrorMsg = res.callStatusMessage;
setState({ ...state });
}
})
.catch(err => {
state.fetchInProg = false;
state.fetchError = true;
state.fetchErrorMsg = 'Error fetching Item Details - ' + err.toString();
setState({ ...state });
});
}, []);
const expandGrpChange = (e: GridExpandChangeEvent) => {
let dr: TcbObjMilestoneGrp = e.dataItem;
let ml = state.milestoneList;
let mlg = ml.find(x => x.milestoneId === dr.milestoneId)!;
mlg.isExpanded = !e.dataItem.isExpanded;
state.fetchErrorMsg = 'Expanded ' + mlg.isExpanded;
setState({ ...state});
}
const renderMilestoneDetails = (e: GridDetailRowProps) => {
return (<section><p>TEST</p></section>);
};
if (state.fetchInProg)
return loadingDiv();
let formatStr = "{0:dd-MMM-yyyy HH:mm }";
return (
<>
<p>{state.fetchErrorMsg}</p>
<Grid
data={state.milestoneList}
detail={renderMilestoneDetails}
expandField="isExpanded"
onExpandChange={expandGrpChange}
resizable
>
<GridColumn field="milestoneDesc" title="Milestone" className="TcbObjMilestoneGridMainCell" />
<GridColumn field="latestMilestoneDate" title="Latest" format={formatStr} width="120px" className="TcbObjMilestoneGridCell" />
<GridColumn field="latestSource" title="Source" width="90px" className="TcbObjMilestoneGridCell" />
</Grid>
</>
);
}
export default TcbObjMilestones;
I managed to solve this.
My mistake was to try to save the data as part of the other state variables.
Once I created a separate useState to handle the data array it all worked perfectly.
Cheers
Mike