Hello,
https://imgur.com/a/1zohd9u
I ask how to rerender master grid when i click in button from the detail grid (look the picture).
Once i click in Rejected/Accepted button in detail grid, the database will be updated and the statut field of master grid change (in database).
but the new value not displayed because i have to manually refresh the page.
I need to setState the data of the master grid to refresh it and display the updated value of Statut field knowing that the button is in detail grid, so how to get access to function that update the state of master grid data ?
Thank you
master grid :
import { GridColumn as Column, Grid, GridDetailRow } from
'@progress/kendo-react-grid'
;
import MyCustomCell from
'../grids/CustomCell'
;
import React from
'react'
;
import axios from
"axios"
;
import { filterBy } from
'@progress/kendo-data-query'
;
import gridDetailInputSecondLevel from
'../gridsDetails/gridDetailInputSecondLevel'
;
const loadingPanel = (
<div className=
"k-loading-mask"
>
<span className=
"k-loading-text"
>Loading</span>
<div className=
"k-loading-image"
></div>
<div className=
"k-loading-color"
></div>
</div>
);
const dataStateDetail1 = {
posts: [],
sort: [],
take: 25,
skip: 0,
total_record: 10000,
pageNumber: 1,
filterUrl:
''
};
class gridDetailInputFirstLevel extends GridDetailRow {
terminalid = window.SERVER_DATA.terminalid;
functionid = window.SERVER_DATA.functionid;
hostname = window.SERVER_DATA.hostname;
jobId =
this
.props.dataItem.jobId;
state = {
filter: {
logic:
"and"
,
filters: []
},
filterInUrl:
''
,
dataStateDetail1: dataStateDetail1,
isLoading:
true
};
// constructeur
constructor(props) {
super
(props);
this
.CustomCell = MyCustomCell(
this
.getPostsDetailLevl1);
}
componentDidMount() {
this
.getPostsDetailLevl1();
}
// MycustomParam = (props) => <MyCustomCell {...props} myfonct = {this.getPostsDetailLevl1}/>
// {...props} spread operator
render() {
const { isLoading, dataStateDetail1 } =
this
.state;
return
(
<div>
{isLoading && loadingPanel}
<Grid
data={filterBy(dataStateDetail1.posts,dataStateDetail1.filter)}
skip={dataStateDetail1.skip}
take={dataStateDetail1.take}
total={dataStateDetail1.total_record}
pageable
filterable
sortable
onPageChange={
this
.pageChange}
filter={
this
.state.filter}
onFilterChange={
this
.onFilterChange}
total={
this
.state.dataStateDetail1.total_record}
detail={gridDetailInputSecondLevel}
expandField=
"expanded"
onExpandChange={
this
.expandChange}
>
<Column field=
"jobId"
title=
"JOB ID"
filterable={
false
} width=
"120px"
/>
<Column field=
"PurchaseOrderNumber"
title=
"PO NUMBER"
width=
"170px"
/>
<Column field=
"Statut"
title=
"STATUS"
width=
"170px"
/>
<Column filter=
"date"
format=
"{0:yyyy-MM-dd}"
field=
"PODate"
title=
"PO DATE"
width=
"170px"
/>
<Column field=
"ReceiverISA"
title=
"PARTNER"
/>
<Column field=
"POType"
title=
"PO TYPE"
width=
"170px"
/>
<Column
width=
"200px"
filterable={
false
}
cell={
this
.CustomCell}/>
</Grid>
</div>
);
}
// cette fct permet d'ouvrir une sous grid
expandChange = (event) => {
event.dataItem.expanded = event.value;
let jobId = event.dataItem.jobId;
this
.setState({ ...
this
.state });
if
(!event.value || event.dataItem.tt_order_line) {
return
;
}
}
/* // par la programmation laisser le row expanded
keepExpanded = (dataItem) => {
dataItem.expanded = true;
this.setState({});
} */
// formatter les dates dans le fichier json
replacerDateinJSON (key, value) {
if
(key ===
'podate'
) {
var
d =
new
Date(value);
d.setDate(d.getDate() + 1);
return
new
Date(d);
}
return
value;
}
formatDateForFiltre = (e) => {
if
(e.field ===
"podate"
)
{
var
d =
new
Date(e.value);
var
month =
""
+ (d.getMonth() + 1);
var
day =
""
+ d.getDate();
var
year = d.getFullYear();
if
(month.length < 2) month =
"0"
+ month;
if
(day.length < 2) day =
"0"
+ day;
return
[day,month,year].join(
"/"
);
}
return
e.value;
}
getPostsDetailLevl1 = () => {
/* let ji;
if (d != undefined) {
ji = d.tt_order[0].jobId;
} */
axios
.get(
this
.hostname+`edipo/xediPurchaseOrder.p?terminalid=` +
this
.terminalid +
"&Funct=bb1.EdiManager"
+
"&FunctionID="
+
this
.functionid +
"&pageSize=25"
+
"&skip="
+
this
.state.dataStateDetail1.skip +
"&take="
+
this
.state.dataStateDetail1.take +
"&page="
+
this
.state.dataStateDetail1.pageNumber +
"&lastRecord=false"
+
"&filter[logic]=and&filter[filters][0][field]=jobId&filter[filters][0][operator]=eq&filter[filters][0][value]="
+
this
.jobId +
(
this
.state.filterUrl ?
this
.state.filterUrl :
''
)
)
.then(response => {
let pos = response.data.ProDataSet.tt_order ? response.data.ProDataSet.tt_order:[];
// let pos = response.data.ProDataSet.tt_order ? response.data.ProDataSet.tt_order.map(dataItem => ji===dataItem.jobId?Object.assign({ expanded: !dataItem.expanded }, dataItem):dataItem):[];
// format date to dd/MM/yyyy
pos = JSON.parse(JSON.stringify(pos),
this
.replacerDateinJSON);
this
.setState({
dataStateDetail1: {
...
this
.state.dataStateDetail1,
posts: pos,
total_record: response.data.ProDataSet.tt_Misc[0].total_record,
},
isLoading:
false
});
})
.
catch
(error =>
this
.setState({ error, isLoading:
false
}));
}
pageChange = (event) => {
this
.setState({
dataStateDetail1: {
...
this
.state.dataStateDetail1,
skip: event.page.skip,
take: event.page.take,
pageNumber: (event.page.skip + event.page.take) / 25
},
isLoading:
true
},()=>{
this
.getPostsDetailLevl1();});
}
onFilterChange = (event) => {
let filterUrl =
''
;
// créer le filtre à ajouter dans l'url
if
(event.filter !=
null
){
const filters = event.filter.filters;
filters.map((filedValue,index) => {
filterUrl = filterUrl +
"&filter[filters]["
+ (index + 1) +
"][operator]="
+ filedValue.operator +
"&filter[filters]["
+
(index + 1) +
"][value]="
+
this
.formatDateForFiltre (filedValue) +
"&filter[filters]["
+ (index + 1) +
"][field]="
+ filedValue.field;
}
);
}
console.log(
"filterUrl"
,filterUrl);
this
.setState({
dataStateDetail1: {
...
this
.state.dataStateDetail1,
skip: 0},
filter: event.filter,
filterUrl,
isLoading:
true
},()=>{
this
.getPostsDetailLevl1()});
}
}
export
default
gridDetailInputFirstLevel;
detail grid :
import { GridColumn as Column, Grid, GridDetailRow } from
'@progress/kendo-react-grid'
;
import { Dialog, DialogActionsBar } from
'@progress/kendo-react-dialogs'
;
import React, { useState } from
'react'
;
import { Button } from
"@progress/kendo-react-buttons"
;
import MyCustomCell from
'../grids/CustomCell'
;
import axios from
"axios"
;
import { filterBy } from
'@progress/kendo-data-query'
;
const loadingPanel = (
<div className=
"k-loading-mask"
>
<span className=
"k-loading-text"
>Loading</span>
<div className=
"k-loading-image"
></div>
<div className=
"k-loading-color"
></div>
</div>
);
const dataStateDetail2 = {
posts: [],
sort: [],
take: 25,
skip: 0,
total_record: 10000,
pageNumber: 1,
filterUrl:
''
};
const ConfirmAcceptPoLine = (props) => {
return
(
<td>
<Button
icon=
"track-changes-enable"
title=
"Confirm"
primary={
true
}
className=
"k-button"
onClick={props.myProp}
style={{ paddingLeft:55, paddingRight:55 }}
>
Envoyer
</Button>
</td>
);
}
class gridDetailInputSecondLevel extends GridDetailRow {
terminalId = window.SERVER_DATA.terminalid;
functionId = window.SERVER_DATA.functionid;
hostname = window.SERVER_DATA.hostname;
PurchaseOrderNumber =
this
.props.dataItem.PurchaseOrderNumber;
rowRender(trElement, props) {
const st = props.dataItem.Statut;
const green = { backgroundColor:
"rgb(55, 180, 0,0.32)"
};
const red = { backgroundColor:
"rgb(243, 23, 0, 0.32)"
};
const defau = {};
let val = {};
switch
(st) {
case
'Accepted'
: val = green;
break
;
case
'Rejected'
: val = red;
break
;
default
: val = defau;
}
const trProps = { style: val };
return
React.cloneElement(trElement, { ...trProps }, trElement.props.children);
}
state = {
filter: {
logic:
"and"
,
filters: []
},
filterInUrl:
''
,
dataStateDetail2: dataStateDetail2,
isLoading:
true
,
visible:
false
};
// constructeur
constructor(props) {
super
(props);
this
.CustomCell = MyCustomCell(
this
.getPostsDetailLevl2);
}
toggleDialog = () => {
this
.setState({
visible: !
this
.state.visible
});
}
toggleDialogNo = () => {
this
.setState({
visible: !
this
.state.visible
});
console.log(
"Nooooo"
);
}
toggleDialogYes = () => {
this
.setState({
visible: !
this
.state.visible
});
this
.processOrdre();
}
componentDidMount() {
this
.getPostsDetailLevl2();
}
MyCell = (props) => <ConfirmAcceptPoLine {...props} myProp={
this
.toggleDialog} />
render() {
const { isLoading, dataStateDetail2 } =
this
.state;
return
(
<div>
{isLoading && loadingPanel}
<Grid
data={filterBy(dataStateDetail2.posts,dataStateDetail2.filter)}
skip={dataStateDetail2.skip}
take={dataStateDetail2.take}
total={dataStateDetail2.total_record}
pageable
filterable
sortable
// height="200px"
onPageChange={
this
.pageChange}
filter={
this
.state.filter}
onFilterChange={
this
.onFilterChange}
total={
this
.state.dataStateDetail2.total_record}
rowRender={
this
.rowRender}
>
<Column field=
"PurchaseOrderNumber"
title=
"PO Number"
filterable={
false
}/>
<Column field=
"POLineNumber"
title=
"PO Line Number"
/>
<Column field=
"Statut"
title=
"STATUS"
/>
<Column field=
"VendorProductNumberCode"
title=
"ITEM"
/>
<Column field=
"Descriptionsequence"
title=
"DESCRIPTION"
/>
<Column field=
"OrderedQty"
title=
"ORDERED QTY"
/>
<Column field=
"SellingPrice"
title=
"SELLING PRICE"
/>
<Column
width=
"200px"
filterable={
false
}
cell={
this
.CustomCell }
footerCell={
this
.MyCell}
/>
</Grid>
{
this
.state.visible && <Dialog title={
"Please confirm"
} onClose={
this
.toggleDialog}>
<p style={{ margin:
"25px"
, textAlign:
"center"
}}>Are you sure you want to
continue
?</p>
<DialogActionsBar>
<button className=
"k-button"
onClick={
this
.toggleDialogNo}>No</button>
<button className=
"k-button"
onClick={
this
.toggleDialogYes}>Yes</button>
</DialogActionsBar>
</Dialog>}
</div>
);
}
// formatter les dates dans le fichier json
replacerDateinJSON (key, value) {
if
(key ===
'deliveryreq'
) {
var
d =
new
Date(value);
d.setDate(d.getDate() + 1);
return
new
Date(d);
}
return
value;
}
formatDateForFiltre = (e) => {
if
(e.field ===
"deliveryreq"
)
{
var
d =
new
Date(e.value);
var
month =
""
+ (d.getMonth() + 1);
var
day =
""
+ d.getDate();
var
year = d.getFullYear();
if
(month.length < 2) month =
"0"
+ month;
if
(day.length < 2) day =
"0"
+ day;
return
[day,month,year].join(
"/"
);
}
return
e.value;
}
getPostsDetailLevl2 = () => {
axios
.get(
this
.hostname+`edipo/xediPurchaseOrderLine.p?terminalid=` +
this
.terminalId +
"&Funct=bb1.EdiManager"
+
"&FunctionID="
+
this
.functionId +
"&pageSize=25"
+
"&skip="
+
this
.state.dataStateDetail2.skip +
"&take="
+
this
.state.dataStateDetail2.take +
"&page="
+
this
.state.dataStateDetail2.pageNumber +
"&lastRecord=false"
+
"&filter[logic]=and&filter[filters][0][field]=PurchaseOrderNumber&filter[filters][0][operator]=eq&filter[filters][0][value]="
+
this
.PurchaseOrderNumber +
(
this
.state.filterUrl ?
this
.state.filterUrl :
''
)
)
.then(response => {
let pos = response.data.ProDataSet.tt_order_line ? response.data.ProDataSet.tt_order_line:[];
// format date to dd/MM/yyyy
pos = JSON.parse(JSON.stringify(pos),
this
.replacerDateinJSON);
this
.setState({
dataStateDetail2: {
...
this
.state.dataStateDetail2,
posts: response.data.ProDataSet.tt_order_line,
total_record: response.data.ProDataSet.tt_Misc[0].total_record,
},
isLoading:
false
},()=>{console.log(
this
.state.dataStateDetail2.posts);});
})
.
catch
(error =>
this
.setState({ error, isLoading:
false
}));
}
pageChange = (event) => {
this
.setState({
dataStateDetail2: {
...
this
.state.dataStateDetail2,
skip: event.page.skip,
take: event.page.take,
pageNumber: (event.page.skip + event.page.take) / 25
},
isLoading:
true
},()=>{
this
.getPostsDetailLevl2();});
}
onFilterChange = (event) => {
let filterUrl =
''
;
// créer le filtre à ajouter dans l'url
if
(event.filter !=
null
){
const filters = event.filter.filters;
filters.map((filedValue,index) => {
filterUrl = filterUrl +
"&filter[filters]["
+ (index + 1) +
"][operator]="
+ filedValue.operator +
"&filter[filters]["
+
(index + 1) +
"][value]="
+ filedValue.value +
"&filter[filters]["
+ (index + 1) +
"][field]="
+ filedValue.field;
}
);
}
this
.setState({
dataStateDetail2: {
...
this
.state.dataStateDetail2,
skip: 0},
filter: event.filter,
filterUrl,
isLoading:
true
},()=>{
this
.getPostsDetailLevl2()});
}
processOrdre = () => {
const SESSION = window.SERVER_DATA;
let url = SESSION.hostname +
"edipo/xediPurchaseOrder.p?terminalid="
+
SESSION.terminalid +
"&Funct=bb1.EdiManager"
+
"&FunctionID="
+
SESSION.functionid +
"&po="
+
this
.PurchaseOrderNumber +
"&processed=yes"
axios
.post(url)
.then((res) => {console.log(
"Processed"
);});
}
}
export
default
gridDetailInputSecondLevel;