Summary
I need the input field that appears when the user is in edit mode to be different depending on the value of a different column for that row. E.g. if the user is in edit mode and Column X
has value A
, then Column Y
should be a text entry field. If, however, Column X
has value B
, then Column Y
should be a dropdown select list. Importantly, this must not affect any other rows (i.e. the fact that Column Y
might be a text entry field for this row should not affect the input type on any other row).
Mockup
In case it wasn’t clear what I was asking for, here is a mockup that shows the functionality I’m after.
1. Target type is 'Group', so 'Target' field is numeric entry
2. Target type is 'Address', so 'Target' field is a select list of strings. Notice that the other rows entries are unaffected (i.e. they are still numeric fields)
More detail
I am creating a lighting control app, and am using material-table as the means through which users specify what actions a button can take (it could be a single action, in which case the table would be a single row, or many actions, in which case the table would be many rows). They can either control a single device, which is stored in a database and should be selectable from a dropdown list, or a group of devices, in which case they manually enter the number of the group they wish to control.
Code
This code forms the basis of the mockups (above):
import React from "react";
import MaterialTable from 'material-table';
const devices = ["Device A (Stairs)", "Device B (Hallway)"];
export default class ControlSpecificationTable extends React.Component {
constructor(props) {
super(props);
this.state = {
columns: [
{ title: 'Step', field: 'step' },
{ title: 'Target Type', field: 'target_type', lookup: { 0: 'Address', 1: 'Group' } },
{ title: 'Target', field: 'target', initialEditValue: '0', lookup: { 0: devices[0], 1: devices[1] }},
// { title: 'Target', field: 'target', initialEditValue: '0', type:'numeric'},
{
title: 'Control Type',
field: 'control_type',
lookup: { 0: 'Button', 1: 'Slider', 2: 'Arrows' },
},
{
title: 'Command type',
field: 'command_type',
lookup: { 0: 'Arc level', 1: 'Minimum', 2: 'Maximum' }
},
{
title: 'Command Value',
field: 'command_value',
},
{
title: 'Time Until Next Command (seconds)',
field: 'time_until_next_command',
}
],
data: [
{ step: '1', target_type: 1, target: 1, control_type: 0, command_type: 0, command_value: 23, time_until_next_command: 3 },
{ step: '2', target_type: 1, target: 15, control_type: 1, command_type: 1, command_value: "N/A", time_until_next_command: 1 },
{ step: '3', target_type: 1, target: 13, control_type: 1, command_type: 1, command_value: "N/A", time_until_next_command: 1 },
]
}
}
render() {
return (
<>
<MaterialTable
title="Control Steps"
columns={this.state.columns}
data={this.state.data}
editable={
{
onRowAdd: newData =>
new Promise((resolve, reject) => {
resolve();
}),
onRowUpdate: (newData, oldData) => {
new Promise((resolve, reject) => {
resolve();
})
},
onRowDelete: oldData =>
new Promise((resolve, reject) => {
resolve();
}),
}
}
/>
</>
)
}
}
You have to keep track of the currently selected target_type and override the editComponent of the columns to show either the drop down or the textField:
editComponent: t =>
this.currentEditingTarget === 0 ? (
<Select
value={t.value}
onChange={e => {
t.onChange(e.target.value);
console.group(e.target.value);
this.currentEditingTarget = e.target.value;
}}
>
<MenuItem value={0}>{devices[0]}</MenuItem>
<MenuItem value={1}>{devices[1]}</MenuItem>
</Select>
) : (
<TextField
value={t.value}
onChange={e => t.onChange(e.target.value)}
type="numeric"
/>
),
Here's a working codesandbox.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With