MUI DataGrid onCellEditStop changes previous value - reactjs

MUI DataGrid
onCellEditStop changes value of previously edited cell when changing other cell.
I saw a post that said that using onCellEditCommit is a solution, but it's deprecated so.. I need another way to fix it
const onCellEditStopHandler = (params: GridCellParams) => {
const { id, field, value } = params;
const faction = staffFactions.find((faction) => faction.id === id);
console.log('triggered');
if (!faction) return;
const factionWithoutActive = staffFactions.filter(
(faction) => faction.id !== id
);
if (field === 'maxVehicles') {
faction.maxVehicles = value;
} else if (field === 'maxMembers') {
faction.maxMembers = value;
}
setStaffFactions([...factionWithoutActive, faction]);
};
<ReactDataGrid
experimentalFeatures={{ newEditingApi: true }}
rows={rows || []}
columns={columns}
onCellEditStop={onCellEditStopHandler}
/>

In the docs, there are many ways that you could handle an editable component.
https://mui.com/x/react-data-grid/editing
For your code, maybe you could check out this section below and try using the processRowUpdate prop. It gets called once the editing stops.
https://mui.com/x/react-data-grid/editing/#persistence

Related

Remove item from String Array ReactJS

I'm working with ReactJS with Typescript and the goal is to have a checkbox component that adds and removes items to a string array according to whether the checkbox is selected or not. My current function only adds to the array, so when I select then unselect a checkbox the item is added twice. Thanks in advance.
Function:
const handleGroupChange = (groupOptions: any) => {
const existSelection = selectedGroups;
existSelection.push(groupOptions.target.value);
setSelectedGroups(existSelection);
}
};
Checkbox:
<FormControlLabel
control={
<Checkbox
color="primary"
onChange={e => handleGroupChange(e)}
value={"MATCHED_MENTORS"}
/>
}
check whether checkbox is checked or not on the onChange event.
const handleGroupChange = (groupOptions: any) => {
const existSelection = selectedGroups;
if (groupOptions.target.checked) {
existSelection.push(groupOptions.target.value);
} else {
var index = existSelection.indexOf(groupOptions.target.value);
if (index !== -1) {
existSelection.splice(index, 1);
}
}
setSelectedGroups(existSelection);
}
You need to check the checkbox boolean property whether it is checked or not. Please follow this example below and here is the Codesandbox
const [selectedGroups, setSelectedGroups] = useState([]);
const handleGroupChange = (groupOptions) => {
let existSelection = selectedGroups;
if (groupOptions.target.checked)
existSelection.push(groupOptions.target.value);
else
existSelection = existSelection.filter(item => item !== groupOptions.target.value)
console.log(selectedGroups);
setSelectedGroups(existSelection);
The thing here is that you are pushing a boolean as item therefore the existSelection array should look something like [true, false, true, false] more or less. That should be something to take a look at if it is the behavior you want.
If I understood corretcly what you want is to practice, maybe you can try this:
const randomStrings = ['gelato', 'frozen_yogurt', 'ice_cream'];
and then when you click on the Checkbox it will trigger onChange wich will be connected to handleGroupChange function and this would look something like:
const handleGroupChange = (isChecked) = {
if(isChecked){
//We create a random number between 0 and 2
const randomIndex = Math.floor(Math.random() * 2);
//We select an element from randomStrings array based on the random
index generated above
const randomStr = this.randomStrings[randomIndex];
//Looks if the randomStr already exist in existSelection
if nothing found it findIndex returns - 1 wich tell us
this item is not in the array so we push it.
const existInArr = this.existSelection.findIndex(randomStr);
if(existInArr === - 1){
existSelection.push(randomStr);
}
//I guess you also wanna feed a useState hook here.
setExistSelection(randomStr);
}
};
This should do the trick.

Fetching label value of switch in react native

I want to achieve functionality of a checkbox with a switch in react-native, as checkbox isn't supported in ios devices. I am not getting on how can I fetch the label value associated with a particular switch.
So, the idea is, I have a bunch of options, say A,B,C and each is associated with a switch, and there is a submit button. On click of submit I want to get the labels of those options which are toggled on.
This is the code for selecting various options and each is associated with a switch,
<Text>A</Text>
<Switch
onValueChange = {this.handleToggle}
value = {toggleValue}
/>
<Text>B</Text>
<Switch
onValueChange = {this.handleToggle}
value = {toggleValue}
/>
<Text>C</Text>
<Switch
onValueChange = {this.handleToggle}
value = {toggleValue}
/>
And handleToggle code is this,
handleToggle = event => {
this.setState(state => ({
toggleValue: !state.toggleValue
}));
}
Thanks a lot.
You are using the same function for different switches, clicking on one of them won't give you access to the label of that particular switch. To do so i would suggest to build it like this. This could be a working solution:
Starting with an array that looks like:
this.state = {
data = [
{
label: "firstSwitch",
checked: false,
},
{
label: "secondSwitch",
checked: false,
}
]
}
Then, in your render:
this.state.data.map((item, index) => <Fragment>
<Text>{item.label}</Text>
<Switch
onValueChange = {() => this.handleToggle(index)}
/>
</Fragment>
)
The handleToggle will update the array in the position passed as argument:
handleToggle = index => {
let tempArr= this.state.data
tempArr[index].checked = !tempArr[index].checked
this.setState({data:tempArr})
}
The submit button will then check for the checked switches:
onSubmit = () => {
let arrOfCheckedSwitches= []
this.state.data.forEach (item => item.checked && arrOfCheckedSwitches.push(item.label))
console.log("array of labels :", arrOfCheckedSwitches)
}
Let me know if there's something that's unclear

Formik checkbox with Semantic-UI styling

Hi,
I've been trying to combine Semantic-UI (Semantic-UI React, to be specific) and Formik, but I keep running into problems. Currently I'm having a problem with checkboxes.
I'm trying to create a generic Formik-aware checkbox component with Semantic-UI styling. This is what I currently have:
const Checkbox = ({ name, title, toggle, fitted, inline }, context) => {
const { formik } = context;
const error = formik.errors[name];
const value = formik.values[name];
return (
<Form.Checkbox
inline={inline}
fitted={fitted}
label={title || (fitted ? null : name)}
name={name}
toggle={toggle}
checked={value ? true : false}
onChange={(e, { name, checked }) => formik.setFieldValue(name, !!checked)}
/>
);
};
Checkbox.contextTypes = { formik: PropTypes.object }
This kind of works. The only problem I'm currently having is with nested values. For example:
<Checkbox name="sections.0.enabled"/>
My Checkbox implementation will use formik.values["sections.0.enabled"] as value, while a formik Field would correctly pick the value from formik.values["sections"][0]["enabled"].
Is there a better way to do this, or should I just flatten the input values?
You can achieve this using lodash.get (https://www.npmjs.com/package/lodash.get) or simply use a function which does the exact same job:
function get( object, keys, defaultVal ){
keys = Array.isArray( keys )? keys : keys.split('.');
object = object[keys[0]];
if( object && keys.length>1 ){
return get( object, keys.slice(1) );
}
return object === undefined? defaultVal : object;
}
Then,
...
const error = get(formik.errors, name);
const value = get(formik.values, name);
...

How to catch remove event in react-select when removing item from selected?

first of all, thanks for awesome work. It makes a lot easier for me. Then here i want to catch remove event, how can I do that? I read the documentation and could not find remove event
I don't think they have an event for that. They just have the onChange.
So, to detect if some option was removed, you would have to compare the current state with the new values the onChange emitted.
Example:
handleOnChange(value) {
let difference = this.state.selected.filter(x => !value.includes(x)); // calculates diff
console.log('Removed: ', difference); // prints array of removed
this.setState({ selected: value });
}
render() {
return (
<div>
<Select
multi={this.state.multi}
options={this.state.options}
onChange={this.handleOnChange.bind(this)}
value={this.state.selected}
showNewOptionAtTop={false}
/>
</div>
);
}
Demo: https://codesandbox.io/s/7ymwokxoyq
React Select exposes a variety of eventListeners to you via props. The onchange function prop now has the following signature. (value: ValueType, action: ActionType).
Accordingly, you can get these events:
select-option, deselect-option, remove-value, pop-value, set-value, clear, create-option, through which you can handle creation and deletion.
Please refer to documentation
They don't have any event for that. I was facing the same problem but in my case, I was needing both the added and removed item. In case someone wants the both values
import 'difference' from 'lodash/difference'
this.currentTags = []
handleChange = (options) => {
const optionsValue = options.map(({ value }) => value)
if (this.currentTags.length < options.length) {
const addedElement = difference(optionsValue, this.currentTags)[0]
this.currentTags.push(addedElement)
console.log("addedElement",addedElement)
//call custom add event here
}
else {
let removedElement = difference(this.currentTags, optionsValue)[0]
console.log("removedElement", removedElement)
// call custom removed event here
let index = this.currentTags.indexOf(removedElement)
if (index !== -1) {
this.currentTags.splice(index, 1)
}
}
}
This code of snippet is working for me to know if any item is removed
I am calling handle change function on onChange event in reat-select
const [selectedGroups, setSelectedGroups] = useState([]);
const handleChange = (value) => {
const diifer = value.length <= selectedGroups.length;
if(diifer){
// item is removed
}
var arr = value.map((object) => object.value);
setSelectedGroups(arr);
};

How can I implement a react callback

Im quite new to react and I am working on a registration page checkbox element
And below is the Choice component implementation,
const ChoiceItem = ( { options, itemId, selectedIndex, onChange } ) => (
handleChange: function(checked){
const value = [];
options.map( option, i ) => (
value[ i ] = checked;
)
},
<Card>
{
options
.map( ( option, i ) => (
<Checkbox
id={ `Choiceitem-checkbox-${ i }-${ itemId }` }
key={ i }
label={ option.text }
style={ styles.checkbox }
value={ '' + i }
onChange={ ( checked ) => onChange( itemId, [ i ], checked ) }
/>
) )
}
</Card>
);
What I want to do over here is to loop through the options and get there values in to an array named value and call back the handleAnswerChange in registration form and set the value over there. Can anyone tell me how I can archive that?
Thank you.
Sounds like the best solution for you is two way binding. You can check out the react docs on adding two way binding.
react two way binding.
Another option would be using jquery
You are actually very close to having this one. I would update your handleChange in MultipleChoiceItem:
handleChange = (index) => (checked) => {
const newValues = options.map((option, i) => {
// if it is the changed returned the new state
// otherwise just return the current value
return index === i ? checked : option;
});
this.props.onChange(this.props.itemId, newValues);
};
Then inside of your render I would set the onChange:
onChange={this.handleChange(i)}
This should then update state on your MyRegisterForm on each checkbox click.

Resources