Validate either array or string with yup schema using formik in reactjs i.e input field is (react-select) - reactjs

[![enter image description here][1]][1]So i am getting data in array from the api and while updating that data i am sending the key value in string. So here comes the problem in validation that the yup is validating the field value as array but i want to validate it in string while updating the data. When i empty the "select" field,it shows me the required message but when i select any option from list the required message doesn't disappear .
Any help will be appreciated.
Thanks!!![![enter image description here]
I just want to make disappear "required" when i select or fill the value in the field
here is the code
//yup formik validation
userservice_area: Yup.lazy(val => (Array.isArray(val) ? Yup.array().of(Yup.string().required("required")) : Yup.string().required("required")))
setLoader(true);
const cityId = userCity
.filter((e) => e.value != undefined)
.map((e) => e.value)
.join(",");
const formdata = new FormData();
formdata.append("first_name", values.first_name);
formdata.append("last_name", values?.last_name);
formdata.append("email", values?.email);
formdata.append(
"phone",
values?.phone?.toString().replace(/\D+/g, "")
);
formdata.append("address", values?.address);
formdata.append("postal_code", values?.postal_code);
formdata.append("province", values?.province);
formdata.append("country", values?.country);
formdata.append("time_zone", values?.time_zone?.value);
formdata.append("user_service_area", cityId);
formdata.append("time_zone", values?.time_zone);

Related

Placeholder disappear after user interact with inputs

I'm facing this issue in my react app:
The application is used for manage storage of a shop, there is one page in which user can add a new obj ( with name , quantity etc.) and there is a page used for UPDATE the obj.
In the "update" page I display the same form of the "new" page but with the current value as placeholder, so that the user can see what value is actually set and change just one or few of the values and leave the others as they are.
The problem is that when the user interact with the input ( like start typing then cancel ) the placeholder disappear and the value is updated as empty.
Now I would like that if user leaves the field empty after interacting with it, the placeholder should appear again, and I would like to make that if the input is left empty then it would not be updated or should be updated with the previous value.
I'm using antd library, so all inputs and stuff are taken from there.
const [data, setData]=useState({
numero: 0,
date: '' ,
nome: "",
...
//get current data
useEffect(() =>get(child(dbRef,'test/' + searchParams.get('id'))).then((snapshot)=>{
if(snapshot.exists()){
setData(snapshot.val())
console.log('[CONVERTED-DATA]',snapshot.val(), '[stato]', data);
}else{
console.log('[GET] NO data available')
}
}).catch((error)=>{
console.log(error)
})
, [])
//now "data" is populated with the values from db
function onChange(e) {
const value = e.target.value ;
setData({
...data,
[e.target.name]: value
});
console.log("[CHANGE-VALUE]", value);
console.log("[event]", e);
}
<Form>
<Form.Item
name="nome"
label="Nome"
rules={[ { type: "string", min: 3 }]}
initialValue={data.nome}
>
<Input
placeholder={data.nome}
value={data.nome}
name="nome"
onChange={onChange}
className="update-input"
/>
</Form.Item>
... more inputs

How to save draft of a long form in ReactJS

I have a long form with over 80 input fields. After submission, it works fine and saves data in a neo4j database. I need to have 'Save Draft' function in case the users want to fill the form later. How can I implement it ?
Edit:
I am trying to save the form data (including empty input fields) into the neo4j database.
I have an array and the form in the constructor:
constructor(props){
super(props);
this.state = {
mydata: {
data1: {},
data2: {},
}
};
this.saveAsDraft = this.saveAsDraft.bind(this);
<form>
<MyInput
title="Name"
inputs={[{title: "name", inputType: "text" }]}
onChange={this.handleChange}
type="freeText"
/>
<MyInput
title="Email"
inputs={[{title: "email", inputType: "text" }]}
onChange={this.handleChange}
type="freeText"
/>
</form>
}
And I used following method to handle the form submission:
async saveAsDraft(){
const name = this.state.mydata['data1']['name'];
const email = this.state.mydata['data1']['email'];
const neo4j = require('neo4j-driver')
const driver = neo4j.driver('bolt://localhost:7687', neo4j.auth.basic('neo4j', 'pass'))
const session = driver.session({database: 'neo4j'})
const txc = session.beginTransaction()
try {
const result = await txc.run(
'CREATE (:Person { name: $name, email: $email })',
{
name: name,
email: email
}
)
await txc.commit()
console.log('commited')
} catch (error) {
console.log(error)
await txc.rollback()
console.log('rolled back')
} finally {
await session.close()
}
}
It works when the input fields are filled. But it shows following error when input fields are empty:
Neo4jError: Expected parameter(s): name, email
how can i handle the empty input fields here ? I want to execute the cypher queries and create nodes and relations with empty input values.
I also need to extract the data later to populate them to the form when the user wants to continue editing the form later.
If it's required to access the form answers from different devices or browsers, then you'll have to store the data into database.
If it's enough, that the users can access the saved form data only on same browser, you can use local storage to achieve that. Some state management libraries like redux and mobxstate tree offer persist feature, so you can persist the whole state of your app in the local storage with minor config.

I need to add predefined - '#domain' when user type on the form?

My form only allows user to type their email without #domainname. for e.g. tomdickharyy#email.com the bit from #email.com is predefined. My handle change function will concatenate "#email.com" at the end. Once the form is submitted on my state i set {email : ''} and the form is empty as expected.
The problem is when I type a new email the form will concatenate #email.com for every letter typed. I don't know how to fix this problem, any help would be great.
handleChange({ target: {name, value} }){
const domainEmail = '#email.com';
name === "email" ? this.setState({ [name]: value + domainEmail}) : this.setState({ [name]: value});
} ```
You have two options:
1) Remove domainEmail and append it again on each change. Some very rude code:
handleChange({ target: {name, value} }) {
const domainEmail = '#email.com';
name === 'email'
? this.setState({ [name]: value.replace(domainEmail, '') + domainEmail })
: this.setState({ [name]: value });
}
2) Move out domainEmail to be purely representational, next to the input field. This is how many UI frameworks do it, see for example Bootstrap: https://getbootstrap.com/docs/4.3/components/input-group/
Then when you submit, remember to append the domain. I recommend this approach, it makes it much less fragile, removing many edge cases. It isalso very clear for the user that they should not type their email.

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']
})

How can I add/remove rows in ag-Grid?

I've using ag-Grid with my React - Typescript project I can set data and get selected data from table but I don't know how to add new empty field and how to remove selected field, I've find on its documents but does not found :(
Using setRowData to set rows so when I want to add new empty field I have to do like
const allNodesData = Array<any>()
this.gridApi.forEachNode((node) => {
allNodesData.push(node.data)
})
allNodesData.push({})
this.gridApi.setRowData(allNodesData)
And when I want to remove selected field I have to do like
const selectedNodes = this.gridApi.getSelectedNodes()
const allNodesData = Array<any>()
this.gridApi.forEachNode((node) => {
if (selectedNodes.indexOf(node) < 0)
allNodesData.push(node.data)
})
this.gridApi.setRowData(allNodesData)

Resources