Antd: How to set nested field value using setFieldsValue - reactjs

So I have a nested dynamic form, and I want to check its value using getFieldsValue. But whenever I do, it doesn't return me the values.
Using ant form hook, I create form list as <Form.List name="guests">
And assign the name to form input <FormInput name={[index, "firstName"]} label='FIRST NAME' />
I am trying to set its value using form.setFieldsValue({ [index, "firstName"]: [value]) but it doesnt works. Any suggestion regarding how to set path.
Strictly need to use setFieldsValue

First get the guests array using form.getFieldValue (You can also use getFieldsValue(['guests'])?.guests).
Then you can modify and set the value like this:
let guests = form.getFieldValue('guests');
// Check If `guests` exist & guest is an array & it's not empty
if (guests && Array.isArray(guests) && guests.length) {
// Check If firstName exists at that `index`
if (guests[index]?.firstName) {
guests[index].firstName = 'New Name';
form.setFieldsValue({ names: guests });
}
}

Related

Yup (with formik and react) - Can't validate array length

kinda new to Yup and I can't figure out how to validate that an array is not empty.
I'm using react + formik + yup + material-ui
here is an example I've created:
https://codesandbox.io/s/new-fire-29onf?file=/src/App.js
I tried in the validationSchema to just use the required method:
validationSchema={Yup.object({ permissions : Yup.array().required('permission cant be empty') })}
i tried to add my functionally using the test method like this:
validationSchema={Yup.object({ permission: Yup.array().test ('notEmptyArr', 'array is empty', (value) =>{ console.log(value); return value.length > 0; }) })}
i also tried to add method to the array like this:
Yup.addMethod(Yup.array, "notEmpty", function(message) { return this.test("notEmpty", message, function(arr) { return Boolean( arr.length > 0 ); }); });
But none of that worked for me : (
if I remove the validation I see the value.permission is indeed an array, with values (if selected)
what am I doing wrong?
thanks
You can use .min():
validationSchema={Yup.object({
permissions: Yup.array().min(1)
})}
UPDATE / WARNING:
Previously only array().required() was required to make sure there was at leas 1 item in the array. For example [] would not pass the test.
⚠️ As of version 0.31.0 (2020-11-23) the behavior of array().required() changed! Now to make sure you have at least 1 item in the array you need to sure: array().required().min(1)
use array().min(1) to handle an empty array error instead of required(); if you use Formik to handle a custom message, use array().min(1, 'your message')

Changing the value of event in CardService.newTextInput does not change the displayed value in textinput in gmail addon

I have simple gmail addon in which i am trying to make custom login form. The problem i am facing is that when i am changing the input field from on Change handler the displayed value is not changing . Trying to hide the password field.
Textinput widget
function getMembersSelectMenu(){
var textInput = CardService.newTextInput()
.setFieldName("Password")
.setTitle("Password")
.setHint("Enter Password")
.setOnChangeAction(CardService.newAction()
.setFunctionName("handlePasswordChange"))
return textInput;
}
handler function for textInput
function handlePasswordChange(e){
// e.formInput.pass = e.formInput.Password;
e.formInput.Password = "*";
e.formInputs.Password = "******"
Logger.log("my value object" + JSON.stringify(e));
}
Already checked the object and value is updated but not change in the view
When textInput field value is change, handlePasswordChange is called with eventObject. I think you're trying to set the value in that eventObject inside handlePasswordChange and not on that field.
I think we can do something like this :
1.Create some global variable to keep track of field.
2.Create field and assign in that variable.
3.On value change set value in that.
var passwordField;
function getMembersSelectMenu(){
passwordField = CardService.newTextInput()
.setFieldName("Password")
.setTitle("Password")
.setHint("Enter Password")
.setOnChangeAction(CardService.newAction()
.setFunctionName("handlePasswordChange"))
return passwordField;
}
function handlePasswordChange(e){
// e.formInput.pass = e.formInput.Password;
passwordField.setValue("*******");
}

Multiple Select not working, only giving last clicked value

I implemented a multiple select dropdown from react-bootstrap documentation.
It does not let me do multiple select and only gets the last clicked option. I have state variable set to array. What else am I missing? App is created with create-react-app.
I have state set to array inside the class constructor. Binding of event handler also done in the constructor.
Next, I'm showing my event handler followed by form group with onChange and value set to state. (note I have a drop-down above this which is working fine.)
I then pass this value to a few classes before it's parsed to JSON. The last pastes are those classes. I have removed other parameters so easier to read, any ideas, feel free to ask for more info.
this.state = {
codeCoverage: [],
}
this.handleCodeCoverageChange = this.handleCodeCoverageChange.bind(this);
//Event handlers below
handleCodeCoverageChange(event){
this.setState({
codeCoverage: event.target.value
})
}
<Form.Group>
<Form.Label>Please choose your desired code coverage software(s)</Form.Label>
<Form.Control as="select" value={this.state.codeCoverage} onChange={this.handleCodeCoverageChange} multiple>
<option value="">--Please choose an option--</option>
<option value="cobertura">Cobertura</option>
<option value="sonarcube">Sonarcube</option>
</Form.Control>
</Form.Group>
var configurator = new Configurator(this.state.codeCoverage)
class Configurator
{
constructor(
code_coverage)
{
this.pipeline = new Pipeline(code_coverage)
}
}
class Pipeline
{
constructor(code_coverage)
{
this.analysisAndSecurity = new AnalysisAndSecurity(code_coverage)
}
class AnalysisAndSecurity{
parameter
constructor(code_coverage)
{
this.code_coverage = code_coverage
}
}
In your handleChange function you assign state.codeCoverage the value of the selected element instead of adding it to the array of selected element. This is why when you select another element it deletes the old value. I would recommend logging e.target.value and this.state.codeCoverage to better understand. As for the solution:
Since you are using multiple select it expects an array as value instead of a single value. So you need to change two things in your handleChange method.
First you need to add your element to existing values and not replace them.
You need to handle when a selected element is clicked again and needs to become unselected.
You can do both these tasks as shown below:
handleChange = e => {
const { codeCoverage } = this.state;
// Find the value selected the codeCoverage array
const index = codeCoverage.indexOf(e.target.value);
// If the value is not found then add it to the array
if (index === -1) codeCoverage.push(e.target.value);
// If value found then remove the value to unselect
else codeCoverage.splice(index, 1);
// Set the state so that the component reloads with the new value
this.setState({ codeCoverage: [...codeCoverage] });
};

How to update dynamic changing fields of json objects using React setState?

I have an object that its fields change dynamically, e.g.,
var Obj = {f1:"", f2:""} or var Obj = {f1:"", f2:"", f3:"" } etc
An input field appears dynamically on screen for every field of the object.
I want to set the state of the object with the values that users enter in each field. How can I do this? I have tried the following code but it doesn't always works correctly.
for (var key in this.state.Obj) {
if (this.state.Obj.hasOwnProperty(key)) {
this.setState({
Obj: update(this.state.Obj, {[key]: {$set: window.$('[name='+key+']')[0].value}}),
})
}
}
As mentioned, you should use an onChange on whatever input fields you need. You could do something like:
<input
type="text"
value={this.state.Obj.f1}
onChange={(e) => {
// Make sure you keep values from other fields
var object = this.state.Obj;
// Modify the value on the object
object.f1 = e.target.value;
// Update the state
this.setState({ Obj: object });
}}
/>

Redux-form validation based on field in other form

I have 2 forms, in which the validation for a field in the second form is based on the value of a field in the first form. This works as expected when filling in the form top-down. However, when I change the value in the first form, the values object isn't updated in the validation.
My validate-function looks something like this:
const validate = values => {
const errors = {}
if (!values.username) {
errors.username = 'Required'
} else if (values.username.length < values.previous_field.length) {
errors.username = 'Your name can't be shorter than the previous field';
}
return errors;
}
When I change the previous field to a short value after filling in a valid username, the username-field never invalidates.
I decided to rename the forms so then would both have the same name. In this way the values do get updated, and you can use the validation in the way I would like.
Both forms are now named userdata, and the first one has all the validation logic:
#reduxForm({
form: 'userdata',
validate,
asyncValidate,
asyncBlurFields: ['car_licenceplate', 'user_zipcode']
})

Resources