setValue in a whole form with react-hook-form - reactjs

I'm building up a user profile that has some addresses, the user can edit them, it's almost finished, but I'm stuck in setting the user edit address in a form.
Just like it shows in the GIF when I click the button no value is set, I'm using react-hook-form to build these forms.
This is the function that execute when I click on the button:
const editAddress = (i) => {
const addressClicked = addressList[i];
console.log(addressWatch());
setAddressValue("name", addressClicked);
setShowForm(true);
};
addressList is an array that is being looped, and then I get the key from the .map(v,i) and it returns an object with all the information that should populate the input fields for the user to edit it.

So, in the docs there is a function that is called "reset" that actually does exactly what I wanted, it wipes the current data from the form and it can replace with a new object data.
https://react-hook-form.com/api/useform/reset
The function looks like this now
const editAddress = (i) => {
const addressClicked = addressList[i];
addressReset(addressClicked);
setShowForm(true);
};

Related

Angular FormControl's material-checkboxes.component has selected values but this.controlValue is an empty array

I have an Angular form I've built that consists of a single material-checkboxes component. I have two copies of this component, one is static and one is dynamic. The only difference is that the dynamic version gets its control values from an API call. Both of these examples have one or more options defaulted as checked when the controls initialize.
The issue I have is that the dynamic one's model is out of sync with its view as long as its left unchanged (ie, if I don't click on any of the checkbox controls to select or unselect them). Once I click on one of the checkboxes, the model updates to sync with the view.
I can tell this because I can submit the static version and get expected results (the defaulted items are posted as values as expected). However, when I submit the dynamic one, I get an empty post.
Here is what the component looks like with the defaulted values before I submit it to see the submitted form data:
And here is the resulted submitted values (as expected):
By way of comparison, here is the same control (material-checkboxes.component.ts) but built using an external datasource to feed in the titleMap and also has defaulted values.
And here is the result after submit of the above form:
So, as the screencaps indicate, The manually created one works as expected and submits the form containing the defaulted values. However, the component with the dynamically generated values, even though the view shows it to have selected default options, submits as EMPTY.
Expected: this.controlValue = ['12', 'd4']
Actual:
onInit > this.controlValue = ['12', 'd4']
After updateValue method > this.controlValue = undefined // But the view is unchanged from the init
However, I can get it to submit data as expected, if I manually change any of the values, even if i set them exactly as they were defaulted. Its as if the form data is not being set until manually clicking on the options.
Here is a snippet from the template that holds the component:
<mat-checkbox
type="checkbox"
[class.mat-checkboxes-invalid]="showError && touched"
[class.mat-checkbox-readonly]="options?.readonly"
[checked]="allChecked"
[disabled]="(controlDisabled$ | async) || options?.readonly"
[color]="options?.color || 'primary'"
[indeterminate]="someChecked"
[name]="options?.name"
(focusout)="onFocusOut()"
(change)="updateAllValues($event)"
[required]="required"
[value]="controlValue">
Update: I found that the issue was that the form control's value is not updated before leaving the syncCurrentValues() method called just after the setTitleMap hostlistener. Adding a call to this.updateValue() in syncCurrentValues() resolves it and the model and view are back in sync. However, there is a problem, but first, here is the code that resolves the issue when there is a default value set in the this.options data:
#HostListener('document:setTitleMap', ['$event'])
setTitleMap(event: CustomEvent) {
if (event.detail.eventName === this.options.wruxDynamicHook && isRequester(this.componentId, event.detail.params)) {
this.checkboxList = buildTitleMap(event.detail.titleMap, this.options.enum, true, true, this.options.allowUnselect || false);
// Data coming in after ngInit. So if this is the first time the list is provided, then use the defaultValues from the options.
const value = this.setDefaultValueComplete ?
this.jsf.getFormControl(this)?.value || [] :
[].concat(this.options?.defaultValue || []);
this.syncCurrentValues(value);
// Set flag to true so we ignore future calls and not overwrite potential user edits
this.setDefaultValueComplete = true;
}
}
updateValue(event: any = {}) {
this.options.showErrors = true;
// this.jsf.updateArrayCheckboxList(this, this.options.readonly ? this.checkboxListInitValues : this.checkboxList);
this.jsf.updateArrayCheckboxList(this, this.checkboxList);
this.onCustomAction(this.checkboxList);
this.onCustomEvent(this.checkboxList);
this.jsf.forceUpdates();
if (this.jsf.mode === 'builder-properties') {
this.jsf.elementBlurred();
}
}
syncCurrentValues(newValues: Array<any>): void {
for (const checkboxItem of this.checkboxList) {
checkboxItem.checked = newValues.includes(checkboxItem.value);
}
this.updateValue(); // Fixed it. Otherwise, the checked items in titlemap never get synced to the model
}
The call to updateData() above fixes the issue in that case. However, when there are no default values in the options data and the checkbox data is loaded externally from an API call that executes after the ngOnInit has fired, I have the same issue. this.controlValue is empty after ngOnInit despite that the view has updated to show checked checkboxes. The model has made that happen through the setTitleMap() method but the controlValue still logs as an empty array.

AgGridReact stop editing and restore old value

I have a react component with an AgGridReact which has an editable column. I want inside the onCellValueChanged event to check if the new value meets some conditions, and if not stop and restore the old value.
I've read that there is an api stopEditing:
https://www.ag-grid.com/documentation/javascript/cell-editing/#editing-api
Here it says:
"stopEditing(cancel): If the grid is editing then editing is stopped. Passing cancel=true will keep the cell's original value and passing cancel=false will take the latest value from the cell editor."
So I've tried using it. Just to test it out I did like this:
const onGridReady = params =>
{
gridApi.current = params.api;
}
const onCellValueChanged = async (event) =>
{
gridApi.current.stopEditing(true);
return;
}
I expected that every time I'll try to edit, no matter what, as soon as I click enter to finish editing, the old value will be restored but it just keeps the new value. The event itself is set properly and it is being invoked.
What am I doing wrong here? And if it's not the way to restore the previous value, what is?
stopEditing is called on the gridApi. By calling stopEditing in your onCellValueChanged, it's too late, the value has already changed.
Here's what you can do instead:
Use a valueSetter for your column. This way, you can accept only certain values and reject all others. For example, this valueSetter will only update the value if the newly entered value is "accept":
function myValuSetter(params) {
if (params.newValue != "accept") {
return false;
}
params.data.make = params.newValue
return true;
}
Demo.

How can I control multiple input object value in map

this is a sample in code sand box
https://codesandbox.io/s/restless-shadow-iiw4p?file=/src/App.jsx
I want to create table that can be added.
However can not control input value.
How can I control multiple input object value in map?
In your code sample you did not call the setValues() function. That's why you could not control the input. Here are some modifications to your code:
const inputName = (index, event) => {
let tempValues = [...values];
tempValues[index].name = event.target.value;
setValues(tempValues);
};
I hope this code will work now. I have tested it in your codesandbox example also.
here is the link to that: https://codesandbox.io/s/purple-water-d74x5?file=/src/App.jsx

how can I separate individual letters from an onChange event in react?

I'm new to React and I have a problem which I don't know how to solve.
I have a state which tracks what I type on the textInput. But when I console.log the input that I type on the textInput, it shows the whole chunks like 'a', 'ab', 'abc' as I type. I want to be able to have control over each input I type like 'a' 'b' 'c', not the whole input like 'abc'. For this, I've tried the map and split function, which made some errors, unfortunately.
Can anyone offer some advice? I'm attaching some of the lines below.
const Words = () => {
const [correctLetters, setCorrectLetters] = useState([]);
const correctLettersHandler = (input) => {
//console.log(input) -> it shows the whole inputs
//const letter = input.map((letter) => letter.split("")); -> failed try
setCorrectLetters(input);
}
return (
<View>
<TextInput
value={correctLetters}
onChangeTedt={correctLettersHandler}
</View>
}
I recommend you take a look at The KeyboardEvent Object to get a full insight on the keyboard events.
At the bottom there are the event types that belong to the KeyboardEvent Object (already mentioned by Derek in a comment to the question):
onkeydown, the event that occurs when the user is pressing a key
onkeypress, the event that occurs when the user presses a key
onkeyup, the event that occurs when the user releases a key

React-Select isMulti retrieve selected options

I'm currently working on a springboot/reactjs project. I'm using the react select library to set a multi select input in one of my forms but I could not get the selected values here's some code to make it a bit clearer.
these are my options generated dynamically from the database each option has the webService Id as a value
this is my select input, I need to get the selected values "Ids" and then call the method that retrieves the webservices from the database and then assign the list of webServices to my newApplicationData.webservices
this is the get web service function
Update : I kind off found a solution to my problem : on the onChange prop I used this
onChange={(selectedOptions) => {
const state = this.state;
state.selectedWebServices = [];
selectedOptions.forEach((option) => {
this.getWS(option.value);
state.selectedWebServices.push(this.state.getWSData);
});
state.newApplicationData.webServices =
state.selectedWebServices;
this.setState(state);
}}
and then I found out another problem: even if I select two deffrent options the list of selected options only gets one duplicated option????!!!!

Resources