MUI Tree select - Set Value programatically - javascript

Hi Im using this package, All working fine but I can't select a value by default programatically which is user selected already using same component .
https://codesandbox.io/s/github/mikepricedev/mui-tree-select
Developer saying use this doc https://mikepricedev.github.io/mui-tree-select/interfaces/TreeSelectProps.html#value we can set, But I cant understand. Pls help me fix it.

Here is a working example of how to use a default value. I have changed this source to have an initial value programatically. value: "2:0"
import React, { useCallback, useState } from "react";
import TreeSelect, { BranchNode, defaultInput } from "mui-tree-select";
const generateOptions = (parentBranch, randomAsync = true) => {
const depth = parentBranch
? Number.parseInt(parentBranch.valueOf().label.split(":")[0]) + 1
: 0;
const options = [];
for (let i = 0, len = Math.ceil(Math.random() * 10); i < len; i++) {
const option = `${depth}:${i}`;
options.push(new BranchNode({ label: option }, parentBranch), option);
}
return randomAsync && Math.random() > 0.5
? new Promise((resolve) => {
setTimeout(() => {
resolve(options);
}, Math.ceil(Math.random() * 1000));
})
: options;
};
const getOptionLabel = (option) =>
option instanceof BranchNode ? option.valueOf().label : option.toString();
const defaultBranch = BranchNode.createBranchNode([
{ label: "0:5" },
{ label: "1:2" }
]);
const Sample = () => {
const [state, setState] = useState({
single: {
value: "2:0",
options: generateOptions(defaultBranch, false),
loading: false,
branch: defaultBranch
},
multiple: {
value: [],
options: generateOptions(null, false),
loading: false,
branch: null
}
});
return (
<div style={{ width: 350, padding: 16 }}>
<TreeSelect
branch={state.single.branch}
onBranchChange={(_, branch) => {
const options = generateOptions(branch);
if (options instanceof Promise) {
setState((state) => ({
...state,
single: {
...state.single,
branch,
loading: true
}
}));
options.then((options) => {
setState((state) => ({
...state,
single: {
...state.single,
options,
loading: false
}
}));
});
} else {
setState((state) => ({
...state,
single: {
...state.single,
branch,
options,
loading: false
}
}));
}
}}
options={state.single.options}
loading={state.single.loading}
getOptionLabel={getOptionLabel}
renderInput={useCallback(
(params) =>
defaultInput({
...params,
variant: "outlined",
label: "Single"
}),
[]
)}
value={state.single.value}
onChange={useCallback(
(_, value) => {
setState((state) => ({
...state,
single: {
...state.single,
value
}
}));
},
[setState]
)}
/>
<div style={{ height: "16px" }} />
<TreeSelect
onBranchChange={(_, branchOption) => {
const options = generateOptions(branchOption);
if (options instanceof Promise) {
setState((state) => ({
...state,
multiple: {
...state.multiple,
loading: true
}
}));
options.then((options) => {
setState((state) => ({
...state,
multiple: {
...state.multiple,
options,
loading: false
}
}));
});
} else {
setState((state) => ({
...state,
multiple: {
...state.multiple,
options,
loading: false
}
}));
}
}}
options={state.multiple.options}
loading={state.multiple.loading}
getOptionLabel={getOptionLabel}
freeSolo
multiple
renderInput={useCallback(
(params) =>
defaultInput({
...params,
variant: "outlined",
label: "Multiple"
}),
[]
)}
/>
</div>
);
};
export default Sample;

Hi I have got solution, That you have to pass particular object with
const [value, setValue] = useState(null);
useEffect(() => {
if (defaultIndustries !== null) {
setValue(() => new Node(defaultIndustries));
}
}, [defaultIndustries]);
And
<TreeSelect
getChildren={(node) =>
syncOrAsync(
node
? node.getChildren()
: industryMultiTree.map((country) => new Node(country)),
runAsync
)
}
getOptionDisabled={(option) => {
var _a;
return (
option.isBranch() &&
!((_a = option.getChildren()) === null || _a === void 0
? void 0
: _a.length)
);
}}
getParent={(node) => syncOrAsync(node.getParent(), runAsync)}
isBranch={(node) => syncOrAsync(node.isBranch(), runAsync)}
isOptionEqualToValue={(option, value) => {
return option instanceof FreeSoloNode ? false : option.isEqual(value);
}}
value={value}
renderInput={(params) => (
<TextField
{...params}
label={label}
error={error}
helperText={helperText}
/>
)}
sx={{ mb: 3 }}
onChange={(_, value) => {
onChangeSelect(value);
}}
/>

Related

Adding sortInfo and/or filterValue to DataGrid breaks sorting/filtering functionality

I am trying to add some 'save preferences' functionality to a DataGrid using https://reactdatagrid.io/docs/miscellaneous but when I add sortInfo makes columns unsortable, the same happens for filterValue (trying to save filtering strings/data). Code here:
import React, { useCallback, useState } from 'react';
import DataGrid from '#inovua/reactdatagrid-enterprise';
import { columnFilters, eeOverviewColumns, filterTypes } from "./overview-columns";
import '#inovua/reactdatagrid-enterprise/index.css';
import { TypeRowProps, TypeRowSelection } from '#inovua/reactdatagrid-community/types';
import { TypeOnSelectionChangeArg } from "#inovua/reactdatagrid-community/types/TypeDataGridProps"
import { Button, FormControl, MenuItem, Select, SelectChangeEvent, TextField } from '#mui/material';
import { TypeColumn, TypeFilterValue, TypeSortInfo } from '#inovua/reactdatagrid-enterprise/types';
interface StoreLayout {
columns: TypeColumn[];
sortInfo: TypeSortInfo;
columnOrder : string[];
filterValue: TypeFilterValue;
}
let STORE: StoreLayout = {
columns: eeOverviewColumns,
sortInfo: [],
columnOrder: eeOverviewColumns.map(ee => ee.name) as string[],
filterValue: columnFilters,
}
let VIEWS= [
{
id: 0,
name: "Default view",
state: STORE
}
]
const EEOverview = (props: any) => {
const dataSource = props.eeData
// Checkbox selection
const [selected, setSelected] = useState<TypeRowSelection>();
const onSelectionChange = useCallback(
(config: TypeOnSelectionChangeArg) => {
setSelected(config.selected)
},
[],
);
const goToEe = useCallback((rowProps: TypeRowProps) => {
window.location.href = `${window.location.href}/${rowProps.data.key}`;
}, [])
const initialState = Object.assign({}, STORE, {});
const [state, setState] = useState(initialState);
const [viewName, setViewName] = useState('')
const sendViewName = (viewName: string) => { setViewName(viewName) }
const saveState = () => {
if (!viewName || viewName.length === 0 ) {
alert("View name not provided")
return
}
STORE = {
columnOrder: state.columnOrder,
columns: state.columns,
sortInfo: state.sortInfo,
filterValue: state.filterValue
}
setState(Object.assign({}, state, {}))
if(VIEWS.map(view => view.name).some(name => name === viewName)) {
const view = VIEWS.find(view => view.name === viewName)!
view.state = state
} else {
VIEWS.push({
id: VIEWS.length,
name: viewName,
state: state
})
}
}
const onSortInfoChange = (sortInfo: TypeSortInfo) => {
setState(Object.assign({}, state, { sortInfo }));
}
const onColumnOrderChange = (columnOrder: string[]) => {
setState(Object.assign({}, state, { columnOrder }));
}
const onFilterValueChange = (filterValue: TypeFilterValue) => {
setState(Object.assign({}, state, { filterValue }));
}
const onBatchColumnResize = (batchColumnInfo: any, { reservedViewportWidth }: any) => {
const colsMap = batchColumnInfo.reduce((acc: any, colInfo: any) => {
const { column, width, flex } = colInfo
acc[column.name] = { width, flex }
return acc
}, {})
const columns = state.columns.map((c: any) => {
return Object.assign({}, c, colsMap[c.name])
})
setState(Object.assign({}, state, {
columns,
reservedViewportWidth
}))
}
return (
<div>
<ViewSelector state = {state} onChange = {setState} ></ViewSelector>
<ViewText onChange = {sendViewName} ></ViewText>
<Button sx={{ mx: 2, my: 2, minWidth: 80 }} variant="contained"
onClick = {saveState}
>
Save view
</Button>
<DataGrid
idProperty="key"
theme="default-light"
className="data-grid"
defaultFilterValue={columnFilters}
filterTypes={filterTypes}
filterValue={state.filterValue} //<- here
onRowClick={goToEe}
columns={state.columns}
sortInfo={state.sortInfo} //<- and here
columnOrder={state.columnOrder}
pagination="local"
dataSource={dataSource}
onSelectionChange={onSelectionChange}
sortable={true}
checkboxColumn
selected={selected}
enableSelection={true}
onSortInfoChange={onSortInfoChange}
onBatchColumnResize={onBatchColumnResize}
onColumnOrderChange={onColumnOrderChange}
onFilterValueChange={onFilterValueChange}
/>
</div>
);
}
export default EEOverview;
const ViewText = ({onChange}: {onChange: any}) => {
const onViewNameChange = (viewName: string) => {
onChange(viewName)
}
return (
<TextField sx={{ mx: 2, my: 2 }}
id="search"
variant="outlined"
size="small"
label="Name current view"
onChange={(e: React.ChangeEvent<HTMLInputElement>) => { onViewNameChange(e.target.value) }}
/>
)
}
const ViewSelector = ({state, onChange}: {state:any, onChange: any}) => {
const [selectedView, setSelectedView] = useState(0)
const handleViewChange = (event: SelectChangeEvent<number>) => {
const selectedView = VIEWS.find(view => view.id===event.target.value)!
setSelectedView(selectedView.id)
const selectedState = selectedView.state
onChange(Object.assign({},selectedState, {}))
}
return (
<FormControl sx={{ m: 2, minWidth: 140 }} >
<Select labelId="view" variant="standard" size="medium" value={selectedView}
renderValue={(selected: any) => { return <div>{VIEWS[selected].name}</div>; }}
onChange={handleViewChange}>
{VIEWS.map((val, key) => (
<MenuItem value={key}>{val.name}</MenuItem>
))}
</Select>
</FormControl>
)
}
If I remove sortInfo/filterValue from passing to DataGrid, it behaves correctly, but it won't be saved to preferences.
Tried to move dataSource from props to state but it has the same behaviour

How to customize Ant table rowselection

I used Ant table to show some information.
https://codesandbox.io/s/proud-architecture-lsb85?file=/src/index.js
I want to customize the position of the checkbox for row selection.
In this application, you can see the header in the following order of checkbox, Name, Age, Address but I want to swap checkbox and Name.
You can add checkbox columns and customize render and titleRender of it to checkbox and then handle the events. if you incounter performance issue you have to add some memoization on columns or evenet handlers.
import React from "react";
import ReactDOM from "react-dom";
import "antd/dist/antd.css";
import { Table, Button, Checkbox } from "antd";
const data = [];
for (let i = 0; i < 46; i++) {
data.push({
key: i,
name: `Edward King ${i}`,
age: 32,
address: `London, Park Lane no. ${i}`
});
}
class App extends React.Component {
constructor(props) {
super(props);
this.state = {
selectedRowKeys: [], // Check here to configure the default column
loading: false,
allChecked: false
};
this.columns = [
{
title: "Name",
dataIndex: "name"
},
{
dataIndex: "checked",
title: () => {
return (
<Checkbox
checked={this.state.allChecked}
onChange={(e) => this.selectAll(e)}
></Checkbox>
);
},
render: (text, rec, index) => {
return (
<Checkbox
checked={
this.state.selectedRowKeys.includes(rec.key) ||
this.state.allChecked
}
onChange={(e) => this.onChange(e, rec)}
></Checkbox>
);
}
},
{
title: "Age",
dataIndex: "age"
},
{
title: "Address",
dataIndex: "address"
}
];
}
start = () => {
this.setState({ loading: true });
// ajax request after empty completing
setTimeout(() => {
this.setState({
selectedRowKeys: [],
loading: false
});
}, 1000);
};
onChange = (e, rec) => {
const checked = e.target.checked;
if (checked) {
this.setState((state) => ({
...state,
selectedRowKeys: [...state.selectedRowKeys, rec.key]
}));
} else {
this.setState((state) => ({
...state,
selectedRowKeys: [
...state.selectedRowKeys.filter((item) => item !== rec.key)
]
}));
}
};
selectAll = (e) => {
const checked = e.target.checked;
if (checked) {
this.setState((state) => ({
...state,
allChecked: true
}));
} else {
this.setState((state) => ({
...state,
allChecked: false
}));
}
};
onSelectChange = (selectedRowKeys) => {
console.log("selectedRowKeys changed: ", selectedRowKeys);
this.setState({ selectedRowKeys });
};
render() {
const { loading, selectedRowKeys } = this.state;
const hasSelected = selectedRowKeys.length > 0;
return (
<div>
<div style={{ marginBottom: 16 }}>
<Button
type="primary"
onClick={this.start}
disabled={!hasSelected}
loading={loading}
>
Reload
</Button>
<span style={{ marginLeft: 8 }}>
{hasSelected ? `Selected ${selectedRowKeys.length} items` : ""}
</span>
</div>
<Table columns={this.columns} dataSource={data} />
</div>
);
}
}
ReactDOM.render(<App />, document.getElementById("container"));

Context state being updated unexpectedly - React Typescript

First time poster so let me know if more information is need.
Trying to figure out why my global state using context API is being updated even when my setSate method is commented out. I thought i might have been mutating the state directly accidently but I dont believe I am
"specialModes" in actionOnClick() is the state in question
const SpecialFunctions: FC = (props: Props) => {
const { currentModeContext, specialModesContext: specialActionsContext, performCalc, inputValueContext } = useContext(AppContext)
const { specialModes, setSpecialModes } = specialActionsContext
const { currentMode, setCurrentMode } = currentModeContext
const { inputValue, setInputValue } = inputValueContext
const categoryOnClick = (index: number) => {
setCurrentMode(specialModes[index])
console.log(specialModes[index].title);
}
const actionOnClick = (action: IAction) => {
let newAction = action
newAction.value = performCalc()
let newSpecialModes = specialModes.map((mode) => {
if (mode === currentMode) {
let newMode = mode
newMode.actions = mode.actions.map((element) => {
if (element === action) {
return newAction
}
else return element
})
return newMode
}
else return mode
})
//setSpecialModes(newSpecialModes)
}
let headings = specialModes.map((categorgy, index) => {
return <Heading isActive={categorgy === currentMode ? true : false} onClick={() => categoryOnClick(index)} key={index}>{categorgy.title}</Heading>
})
let actions = currentMode.actions.map((action, index) => {
return (
<Action key={index} onClick={() => actionOnClick(action)}>
<ActionTitle>{action.title}</ActionTitle>
<ActionValue>{action.value}</ActionValue>
</Action>
)
})
return (
<Wrapper>
<Category>
{headings}
</Category>
<ActionsWrapper toggleRadiusCorner={currentMode === specialModes[0] ? false : true}>
{actions}
</ActionsWrapper>
</Wrapper>
)
}
Context.tsx
interface ContextType {
specialModesContext: {
specialModes: Array<ISpecialModes>,
setSpecialModes: React.Dispatch<React.SetStateAction<ISpecialModes[]>>
},
currentModeContext: {
currentMode: ISpecialModes,
setCurrentMode: React.Dispatch<React.SetStateAction<ISpecialModes>>
},
inputValueContext: {
inputValue: string,
setInputValue: React.Dispatch<React.SetStateAction<string>>
},
inputSuperscriptValueContext: {
inputSuperscriptValue: string,
setInputSuperscriptValue: React.Dispatch<React.SetStateAction<string>>
},
performCalc: () => string
}
export const AppContext = createContext({} as ContextType);
export const ContextProvider: FC = ({ children }) => {
const [SpecialModes, setSpecialModes] = useState([
{
title: 'Rafter',
actions: [
{
title: 'Span',
active: false
},
{
title: 'Ridge Thickness',
active: false
},
{
title: 'Pitch',
active: false
}
],
},
{
title: 'General',
actions: [
{
title: 'General1',
active: false
},
{
title: 'General2',
active: false
},
{
title: 'General3',
active: false
}
],
},
{
title: 'Stairs',
actions: [
{
title: 'Stairs1',
active: false
},
{
title: 'Stairs2',
active: false
},
{
title: 'Stairs3',
active: false
}
],
}
] as Array<ISpecialModes>)
const [currentMode, setCurrentMode] = useState(SpecialModes[0])
const [inputValue, setInputValue] = useState('0')
const [inputSuperscriptValue, setInputSuperscriptValue] = useState('')
const replaceCharsWithOperators = (string: string): string => {
let newString = string.replaceAll(/\s/g, '') // delete white space
newString = newString.replace('×', '*')
newString = newString.replace('÷', '/')
console.log(string)
console.log(newString)
return newString
}
const performCalc = (): string => {
let originalEquation = `${inputSuperscriptValue} ${inputValue} =`
let equation = inputSuperscriptValue + inputValue
let result = ''
equation = replaceCharsWithOperators(equation)
result = eval(equation).toString()
setInputSuperscriptValue(`${originalEquation} ${result}`)
setInputValue(result)
console.log(result)
return result
}
return (
<AppContext.Provider value={
{
specialModesContext: {
specialModes: SpecialModes,
setSpecialModes: setSpecialModes
},
currentModeContext: {
currentMode,
setCurrentMode
},
inputValueContext: {
inputValue,
setInputValue
},
inputSuperscriptValueContext: {
inputSuperscriptValue,
setInputSuperscriptValue
},
performCalc
}}>
{children}
</AppContext.Provider>
)
}
In your mode.actions.map() function you are indirectly changing actions field of your original specialModes array.
To fix this problem you need to create shallow copy of specialModes array Using the ... ES6 spread operator.
const clonedSpecialModes = [...specialModes];
let newSpecialModes = clonedSpecialModes.map((mode) => {
// rest of your logic here
})

Storybook fetch http addons knobs

The result I would like to obtain in the first image, an input field where a url is put from which the data must be taken.
In the second image you see the problem I am getting when I try to get the data from http.
The module works if I don't use it within the storybook.
So I don't understand where the problem is.
Can anyone help me out?
import React, { useState, useEffect } from 'react';
import { storiesOf } from '#storybook/react-native';
import { withKnobs, object, text } from '#storybook/addon-knobs';
import { Chip, Text } from 'react-native-paper';
import Datatable from './DatatableFetch';
const columns = [
{
name: 'Name',
selector: 'name',
sortable: true,
},
{
name: 'Trips',
selector: 'trips',
sortable: true,
cell: ({ trips }) => <Chip mode="outlined">{trips}</Chip>,
right: true,
},
];
const App = ({url}) => {
const [state, setState] = useState({
data3: [],
page: 1,
perPage: 5,
totalRows: 1,
});
const { data3, page, totalRows, perPage } = state;
const child = (obj, str) => {
const props = str.split('.');
let child = obj;
props.forEach((prop) => (child = child[prop]));
return child;
};
const load = (sort, sortField = '', sortAsc = false) =>
fetch(
url +
(page - 1) +
'&size=' +
perPage
)
.then((response) => response.json())
.then(({ data, totalPassengers }) => {
var copyData = Object.assign([], data);
var result = sort
? copyData
: copyData.sort((a, b) => {
let [x, z] = sortAsc ? [a, b] : [b, a];
return child(x, sortField) > child(z, sortField) ? 1 : -1;
});
setState((prev) => ({
...prev,
data3: result,
totalRows: totalPassengers,
}));
})
.catch((error) => {
console.error(error);
});
useEffect(() => {
load(false);
}, [page]);
return (
<Datatable
columns={object('columns', columns, 'Columns')}
data={object('data', data3, 'Data')}
//data={data3}
striped
stripedColors={['#2196f3', '#ccc']}
viewLoader
defaultSortField={'name'}
defaultSortAsc={true}
paginationServer
paginationTotalRows={totalRows}
onChangePage={(_inPage) =>
setState((prev) => ({
...prev,
page: _inPage,
}))
}
onSort={(selector, sortDirection) =>
load(true, selector, sortDirection === 'asc')
}
paginationComponentOptions={(currentPage, totalPage) =>
`${currentPage} di ${totalPage}`
}
style={{
backgroundColor: "#ccc",
borderRadius: 4,
}}
/>
);
};
storiesOf('DatatableFetch', module)
.addDecorator(withKnobs)
.add('example', () => {
return <App url={text("Url", "https://api.instantwebtools.net/v1/passenger?page=", "Url")} />;
});
DatatableFetch.js
import React, { useState, useEffect, useCallback } from 'react';
import { View, Animated } from 'react-native';
import { DataTable, ProgressBar, Colors, Text } from 'react-native-paper';
function Datatable({
columns,
data = [],
noTableHead = false,
striped = false,
stripedColors = ['#2196f3','#8bc34a'],
viewLoader = false,
defaultSortField,
defaultSortAsc,
page: _page = 1,
perPage: _perPage = 5,
pagination = false,
paginationComponentOptions,
noDataComponent = <Text>There are no records to display.</Text>,
style,
paginationServer = false,
paginationTotalRows = 0,
onChangePage,
onSort
}) {
const [state, setState] = useState({
datatable: data,
page: _page - 1,
perPage: _perPage,
numberOfPages: Math.ceil( (paginationServer ? paginationTotalRows : data.length) / _perPage),
sortField: defaultSortField,
sortAsc: defaultSortAsc,
progressBar: false,
loading: false,
});
const {
datatable,
page,
perPage,
numberOfPages,
sortField,
sortAsc,
progressBar,
loading,
} = state;
/*useEffect(() => {
setState((prev) => ({
...prev,
datatable: data,
numberOfPages: Math.ceil( (paginationServer ? paginationTotalRows : data.length) / _perPage)
}));
}, [data]);*/
const dataPagination = !paginationServer && pagination
? datatable.slice(perPage * page, perPage * (page + 1))
: datatable;
const getValue = (object, { selector, cell }) => {
if (cell) return cell(object);
return selector
.replace(/\[/g, '.')
.replace(/\]/g, '')
.split('.')
.reduce((o, k) => (o || {})[k], object);
};
useEffect(() => {
console.log('a')
setState((prev) => ({
...prev,
progressBar: true,
}));
sort(sortField, sortAsc);
}, [data]);
const child = (obj, str) => {
const props = str.split('.');
let child = obj;
props.forEach((prop) => (child = child[prop]));
return child;
};
const sort = async (sortField, sortAsc) => {
var copyData = Object.assign([], data);
var result = paginationServer ? copyData : copyData.sort((a, b) => {
let [x, z] = sortAsc ? [a, b] : [b, a];
return child(x, sortField) > child(z, sortField) ? 1 : -1;
});
setTimeout(() => {
setState((prev) => ({
...prev,
datatable: result,
numberOfPages: Math.ceil( (paginationServer ? paginationTotalRows : result.length) / _perPage),
progressBar: false,
loading: true,
}));
}, 2000);
};
return (
<DataTable style={style}>
{!noTableHead && (
<DataTable.Header>
{columns.map((item, i) => {
const sortDirection =
datatable.length > 0 &&
!progressBar &&
sortField === item.selector
? !sortAsc
? 'ascending'
: 'descending'
: null;
return (
!item.omit && (
<DataTable.Title
key={i}
onPress={() => {
if (item.sortable) {
const sortAscC =
sortField === item.selector ? !sortAsc : true;
setState((prev) => ({
...prev,
sortField: item.selector,
sortAsc: sortAscC,
progressBar: true,
}));
if(paginationServer) onSort(item.selector, sortAscC ? 'asc' : 'desc')
else sort(item.selector, sortAscC);
}
}}
sortDirection={sortDirection}
numeric={item.right}
style={item.styleHeader}>
{item.name} {false && sortDirection}
</DataTable.Title>
)
);
})}
</DataTable.Header>
)}
{viewLoader && progressBar && (
<ProgressBar indeterminate color={Colors.blue900} />
)}
{!progressBar && datatable.length === 0 && (
<View
style={{
margin: 10,
justifyContent: 'center',
alignItems: 'center',
}}>
{noDataComponent}
</View>
)}
{loading &&
dataPagination.map((item, i) => {
return (
<DataTable.Row
key={i}
style={{
opacity: progressBar ? 0.2 : 1,
backgroundColor: striped
? i % 2
? stripedColors[0]
: stripedColors[1]
: null,
}}>
{columns.map((headerItem, j) => {
return (
!headerItem.omit && (
<DataTable.Cell
key={j}
numeric={headerItem.right}
style={headerItem.styleRow}>
{getValue(item, headerItem)}
</DataTable.Cell>
)
);
})}
</DataTable.Row>
);
})}
{(pagination || paginationServer) && (
<DataTable.Pagination
page={page}
numberOfPages={numberOfPages}
onPageChange={(page) => {
onChangePage && onChangePage(page+1)
if(true){
setState((prev) => ({
...prev,
progressBar: true,
}));
setTimeout(() => {
setState((prev) => ({
...prev,
page: page,
progressBar: false,
}));
}, 2000);
}
}}
label={paginationComponentOptions ? paginationComponentOptions(page + 1, numberOfPages) : `${page + 1}-${numberOfPages} of ${datatable.length}`}
/>
)}
</DataTable>
);
}
export default Datatable;

React-data-grid - Changing cell value using global variable upon

I'm trying to create a certain functionality in my react-data-grid.
I have a column called subStart, and I have a dropdown that I want to use so that the user can set the value of a cell to the value of a state variable (this.state.timeTotalSec).
So if the user clicks on "Use Global Time" option in a 'Start Time' cell, it will replace the value of that cell with the value of this.state.timeTotalSec. How on earth do I do this?
I have the dropdown functionality working. But how do I get it to change the cell value?
const rows = [
{ id: 1, subStart: "00:00.000", subEnd: "00:00.000" , subText: 'Text1'},
{ id: 2, subStart: "00:00.000", subEnd: "00:00.000" , subText: 'Text2'},
{ id: 3, subStart: "00:00.000", subEnd: "00:00.000" , subText: 'Text3'}
];
const columns = [
{
key: "id",
name: "ID"
},
{
key: "subStart",
name: "Start Time",
editable: true
},
{
key: "subEnd",
name: "End Time",
editable: true
},
{
key: "subText",
name: "Text",
editable: true
}
].map(c => ({ ...c, ...defaultColumnProperties }));
const subStartActions = [
{
icon: <span className="glyphicon glyphicon-remove" />,
callback: () => {
alert("Deleting");
}
},
{
icon: "glyphicon glyphicon-link",
actions: [
{
text: "Use Global Time",
callback: () => {
// TODO
// **** TRYING TO MAKE THIS WORK ****
}
}
]
}
];
function getCellActions(column, row) {
const cellActions = {
subStart: subStartActions
};
return row.id % 2 === 0 ? cellActions[column.key] : null;
}
const ROW_COUNT = 50;
class App extends React.Component {
constructor (props) {
super(props)
this.state = {
playing: false,
duration: 0,
timeMilli: 0,
timeSec: 0,
timeMin: 0,
timeTotalSec: 0,
rows
}
}
onDuration = (duration) => {
this.setState({ duration })
}
onProgress = (progress) => {
if (this.state.duration == 0) {
return
}
const timeTotalSec = progress.played * this.state.duration
if (timeTotalSec !== this.state.timeTotalSec) {
const timeMin = Math.floor(timeTotalSec / 60)
const timeSec = Math.floor(timeTotalSec - (timeMin)*60)
const timeMilli = (timeTotalSec - timeSec - timeMin*60).toFixed(3)
this.setState({ timeTotalSec })
this.setState({ timeMin })
this.setState({ timeSec })
this.setState({ timeMilli })
}
}
onGridRowsUpdated = ({ fromRow, toRow, updated }) => {
this.setState(state => {
const rows = state.rows.slice();
for (let i = fromRow; i <= toRow; i++) {
rows[i] = { ...rows[i], ...updated };
}
return { rows };
});
};
render () {
const { data } = this;
return (
<div className='player-wrapper'>
<ReactPlayer
url='https://www.youtube.com/watch?v=lhlZkqEag7E'
className='react-player'
playing={this.state.playing}
onPlay={() => this.setState({ playing: true })}
onPause={() => this.setState({ playing: false })}
controls='True'
onDuration={this.onDuration}
onProgress={this.onProgress}
/>
Video is currently: {this.state.playing ? 'playing' : 'paused'}
<br />
Duration: {Math.round(this.state.duration).toString() + ' seconds'}
<br />
Elapsed: {this.state.timeMin + 'min ' + this.state.timeSec + 'sec ' +
this.state.timeMilli + 'ms'}
<br />
<button onClick={() => this.setState({ playing: true })}>Play</button>
<button onClick={() => this.setState({ playing: false })}>Pause</button>
<ButtonToolbar>
<Button variant="primary" onClick={() => this.setState(this.state.playing ? false : true)}>Play/Pause</Button>
</ButtonToolbar>
<ReactDataGrid
columns={columns}
rowGetter={i => this.state.rows[i]}
rowsCount={ROW_COUNT}
// minHeight={500}
getCellActions={getCellActions}
onGridRowsUpdated={this.onGridRowsUpdated}
enableCellSelect={true}
/>
</div>
)
}
}
ReactDataGrid will just render what data you pass to it, If you want to change the value of a cell, you should update the rows from data source or state you are using.in your case rows
this.state = {
playing: false,
duration: 0,
timeMilli: 0,
timeSec: 0,
timeMin: 0,
timeTotalSec: 10,
rows // your datasourse
};
I've supposed,id is your data Key.Add updateRowDate to actions to handle your state changes.
actions: [
{
text: "Use Global Time",
callback: () => {
// TODO
// **** TRYING TO MAKE THIS WORK ****
updateRowDate(row.id);
}
}
]
and here is updateRowDate in App component
updateRowDate = rowId => {
this.setState(prv => ({
rows: prv.rows.map(q => {
if (q.id === rowId) return { ...q, subStart: this.state.timeTotalSec };
return q;
})
}));
finally, you need to pass updateRowDate to getCellActions
<ReactDataGrid
columns={columns}
rowGetter={i => this.state.rows[i]}
rowsCount={ROW_COUNT}
// minHeight={500}
getCellActions={(column, row) =>
getCellActions(column, row, this.updateRowDate)
}
onGridRowsUpdated={this.onGridRowsUpdated}
enableCellSelect={true}
/>
Here is the temporary sandbox containing the fixed version

Categories