How can I optimize my validation code in reactjs? - javascript

Below, I have mentioned my JS code. So, Kindly suggest or guide me that there is any better approach to implement the validation on form submit for react project or is it right approach which i have implemented already?
submitUserForm = (e) => {
e.preventDefault();
const { formError } = this.state;
let valid = true;
if(document.getElementById('useremail').value === "") {
valid = false;
formError.email = "Kindly enter your email id"
}
else {
valid = true;
formError.email = ""
}
if(document.getElementById('userpassword').value === "") {
valid = false;
formError.password = "Kindly enter the password"
}
else {
valid = true;
formError.password = ""
}
if(valid === true) {
this.formSubmitApi();
}
this.setState({
isValid: valid,
formError
})
}

This is how you can improve your code:
submitUserForm = (e) => {
e.preventDefault();
const formError = {}
if(document.getElementById('useremail').value === "") {
formError.email = "Kindly enter your email id"
}
if(document.getElementById('userpassword').value === "") {
formError.password = "Kindly enter the password"
}
Object.keys(formError).length === 0 && this.formSubmitApi();
this.setState({
formError
})
}

First of all, in order to improve your code, you need to have controlled components (Inputs in this case) in order to store your values in the state and then use them in the submitUserForm function, also, instead of valid variable, I'll use a validation function like (Also, make the useremail and userpassword objects, in order to store the errors there):
state = {
useremail: { value: '', error: '' },
userpassword: { value: '', error: '' },
};
validateValue = value => {
return value !== undefined && value !== null && value !== '';
};
submitUserForm = e => {
const { useremail, userpassword } = this.state;
e.preventDefault();
// If both the 'useremail' and the 'userpassword' pass the 'validateValue' validations, then send the data
if (this.validateValue(useremail.value) && this.validateValue(userpassword.value)) {
this.formSubmitApi(useremail.value, userpassword.value);
// After sending the info, we reset our two states to initial state
this.setState({useremail: { value: '', error: '' }, userpassword: { value: '', error: '' } });
} else {
// If 'useremail' don't pass the validation we store the error
if (!this.validateValue(useremail.value)) {
this.setState({ useremail: { value: useremail.value, error: 'Please enter a valid email' }});
}
// If 'userpassword' don't pass the validation we store the error
if (!this.validateValue(userpassword.value)) {
this.setState({ userpassword: { value: userpassword.value, error: 'Please enter a valid password' }});
}
}
};
I think this is a more clean approach, you only have to states instead of three as before and you can get all the information that you need from those states.

I would change 2 things:
Make the inputs controlled, so that you have better and direct control of the input. Accessing the inputs with document.getElementById is bad practice. Save the text of each input within the state or use refs.
I would change the check for valid input into something like this:
const errors = {};
errors.email = "Kindly enter your email id"
if (Object.keys(errors).length === 0) {...}
It should be a new object, so that you don't mutate the state and this makes it easier because you don't have a second variable.
I hope this helps. Happy coding.

Related

when expire date entered, automatic slash

There is a credit card component. It asks the user to enter credit card information. However, I want to automatically put a slash between the day and month when the user enters the credit card expiration date. I searched the expiration date entry as "auto slash when 2 digits are entered" but I haven't been successful yet.
i can write; 0614
The format i want; 06/14
How can I solve it?
js
const [expDateValidationState, setExpDateValidationState] = useState({
error: false,
helperText: '',
});
const expDateOnChange = (event) => {
if (expDateValidator(event.target.value)) {
setExpDateValidationState({ error: false, helperText: '' });
setPaymentInfo({
...paymentInfo,
expDate: event.target.value === '' ? null : event.target.value,
});
} else {
setExpDateValidationState({
error: true,
helperText: 'Please enter your expire date.',
});
setPaymentInfo({
...paymentInfo,
expDate: null,
});
}
const handleExpDateChange = (event) => {
expDateOnChange(event);
handleInputChange(event);
};
validator
export const expDateValidator = (expDate) => {
const expDateRegex = /^(0[1-9]|1[0-2])\/?([0-9]{4}|[0-9]{2})$/;
return expDateRegex.test(expDate);
};
html
<AS.TextField
placeholder="aa/YY"
inputProps={{ maxLength: 5 }}
onChange={handleExpDateChange}
error={expDateValidationState.error}
helperText={expDateValidationState.helperText}
name="expDate"
value={paymentInfo.expDate}
/>
Try this one
const expDateOnChange = (event) => {
if (expDateValidator(event.target.value)) {
setExpDateValidationState({ error: false, helperText: '' });
let value = event.target.value;
if (value.length===2) value += "/"
setPaymentInfo({
...paymentInfo,
expDate: event.target.value === '' ? null : value,
});
} else {
setExpDateValidationState({
error: true,
helperText: 'Please enter your expire date.',
});
setPaymentInfo({
...paymentInfo,
expDate: null,
});
}
When I change some data I usually put it in the state. If you also keep your data in the state, you can modify your handleExpDateChange to something like this:
const [expirationDate, setExpirationDate] = useState();
const handleExpDateChange = (event) => {
if (event.target?.value?.length === 2 && expirationDate.length < 3) {
setExpirationDate(event.target.value + '/')
} else {
setExpirationDate(event.target.value)
}
}
This can be simplified if you use ternary expression or in any other way but this is just very simple and the first thing that came to my mind.
Hope this will be helpful.

Looking for suggestions on how to clean up some conditional statements

Developing a validation function in React. I fairly new and don't want to develop any bad habits while I'm learning so I'm looking for suggestions on how to clean up a block of code i have here.
The function checks input fields and if they're blank, it attaches the appropriate message to an array. Once all input fields are checked, if that array is empty then proceed to submitting form. If that array contains error messages then the message is displayed to screen (not shown)
validation = (event) => {
event.preventDefault();
let errors = []
const {firstName, lastName, emailAddress, password, confirmPassword} = {...this.state}
if(firstName.length === 0) errors.push('Please provide a value for First Name');
if(lastName.length === 0) errors.push('Please provide a value for Last Name');
if(password.length === 0){
errors.push('Please provide a value for Password');
}else if(password !== confirmPassword){
errors.push('Passwords do not match');
};
if(emailAddress.length === 0) {
errors.push('Please provide a value for Email Address');
}else if(!emailRegex.test(emailAddress)){
errors.push('Invalid email address');
};
this.setState({errors: errors})
if(errors.length === 0) this.logIn()
}
logIn = () => {
console.log('good to go')
};
Just looking for ways to clean up my conditional statements, if possible! Thanks
Perhaps something like the below would suffice. You could simplify this greatly if you provided a generic error message such as "Missing required value: <keyName>", as opposed to something specific for the field.
You'll also want to do a manual check to ensure password === confirmPassword, but I think you'll be able to work that piece out.
const emailRegex = <your regex>;
const hasLength = val => val && val.length !== 0;
Validation Map
const validators = {
firstName: {
validate: hasLength,
message: 'Please provide a value for First Name'
},
lastName: {
validate: hasLength,
message: 'Please provide a value for Last Name'
},
password: {
validate: hasLength,
message: 'Please provide a value for Password'
},
emailAddress: [{
validate: hasLength,
message: 'Please provide a value for Email Address'
},
{
validate: val => !emailRegex.test(val),
message: 'Invalid email address'
}
],
}
Validator
validation = (event) => {
event.preventDefault();
let errors = []
const state = {...this.state};
Object
.keys(state)
.forEach(key => {
let validator = validators[key];
if (!validator) return;
if (!Array.isArray(validator)) {
validator = [validator]
}
validator.forEach(v => {
if (!v.validate(state[key])) {
errors.push(v.message)
}
})
});
this.setState({errors: errors})
if (errors.length === 0) this.logIn()
}

Transforming observer object in VueJS

I'm trying to validate the form and usually i do it the way i'm going to put here, problem is that I can't assign object to component object, also it doesn't show it in template if component data changes, should i use watch and how to do it since i learn Vue:
validate(data) {
Object.entries(data).map(field => {
if (field[1] == "") {
errors[field[0]] = "Can't be blank";
} else if ( data.password !== "" &&
field[0] == "confirm_password" &&
field[1] !== data.password {
errors[field[0]] = "Passwords don't match";
}
});
return errors;
},
signUp(data) {
this.errors = JSON.parse(JSON.stringify(this.validate(data)));
console.log(this.errors);
if (Object.keys(this.errors).length == 0) {
this.register(data);
}
}
'data' is object inside the data of the component...
I tried to transform it this way JSON.parse((JSON.stringify(object)), tried also Object.assign({}, this.validate(data)), {...this.validate(data)}

bootstrapvalidator one of two fields required

I have a two phone fields on my form - phone and phone2. Only one of them is required. I have been unable to get the validation to work no matter what I have tried. I have tried callbacks and custom validators and it seems like I just can't get it to work. The way I would like it to work is check each field and if both are empty then display a custom message under each. If either one, or both, has data then go ahead and validate each for correctness. If/when the user clicks submit again, check both fields again and if either or both has status message, remove the message start validation on both all over again. I just cant' seem to get this to work and I don't know if it is as easy as somehow forcing the plugin to revalidate all (or custom selected) fields every time the submit button is hit or what.
Hopefully this makes sense. If not please ask for more detail. I've been struggling with this for a while now and have cotton head.
Basically, one of the two fields needs to have data and that data needs to be valid.
I've seen the post on stackoverflow here: Conditional validation with BootstrapValidator but it looks like the answer was for a different plugin.
Here is what I have been trying:
.bootstrapValidator({
live: 'disabled',
message: 'This value is not valid',
fields: {
phone: {
group: '.col-md-3',
validators: {
callback: {
callback: function(value, validator, $field) {
field_name = $($field).attr('name');
if (value.length == 0 && $('#phone2').val() == '') {
return {
valid: false,
message: 'at least one phone number is required'
}
}
else
{
if ( $('#phone2') == '' )
{
$('#defaultForm')
.bootstrapValidator('resetField', $('#phone2') )
//.bootstrapValidator('updateStatus', $('#phone2'), 'NOT_VALIDATED')
;
}
}
value = value.replace(/\D/g, '');
if ( value != '' ) {
if ( !((/^(?:(1\-?)|(\+1 ?))?\(?(\d{3})[\)\-\.]?(\d{3})[\-\.]?(\d{4})$/).test(value) && (value.length == 10)) ) {
//alert("PHONE DID NOT PASS VALIDATION");
return {
valid: false,
message: 'Phone number is not valid'
}
}
else
{
return true;
}
}
else
{
$('#defaultForm')
.bootstrapValidator('resetField', field_name )
.bootstrapValidator('updateStatus', field_name, 'NOT_VALIDATED')
;
return true;
}
}
}
}
},
phone2: {
group: '.col-md-3',
validators: {
callback: {
callback: function(value, validator, $field) {
field_name = $($field).attr('name');
if (value.length == 0 && $('#phone').val() == '') {
return {
valid: false,
message: 'at least one phone number is required'
}
}
else
{
if ( $('#phone') == '' )
{
$('#defaultForm')
.bootstrapValidator('resetField', $('#phone') )
//.bootstrapValidator('updateStatus', $('#phone'), 'NOT_VALIDATED')
;
}
}
value = value.replace(/\D/g, '');
if ( value != '' ) {
if ( !((/^(?:(1\-?)|(\+1 ?))?\(?(\d{3})[\)\-\.]?(\d{3})[\-\.]?(\d{4})$/).test(value) && (value.length == 10)) ) {
//alert("PHONE2 DID NOT PASS VALIDATION");
return {
valid: false,
message: 'Phone number2 is not valid'
}
}
else
{
return true;
}
}
else
{
$('#defaultForm')
.bootstrapValidator('resetField', field_name )
.bootstrapValidator('updateStatus', field_name, 'NOT_VALIDATED')
;
return true;
}
}
}
}
}
}
})
A little late but...
You have to validate both phone values in both callback functions. When one of the phones is valid, set the other as valid.
fields: {
phone: {
validators: {
callback: {
callback: function (value: any, validator: any, field: any) {
// Get the value of the field 'phone2'
const phone2 = validator.getFieldElements('phone2').val();
// Neither phone and phone2 are valid?
if (!value && !phone2) {
return false;
}
// phone is valid. Update validity of phone2.
validator.updateStatus('phone2', validator.STATUS_VALID);
return true;
},
message: 'at least one phone number is required'
}
}
},
phone2: {
validators: {
callback: {
callback: function (value: any, validator: any, field: any) {
// Get the value of the field 'phone'
const phone = validator.getFieldElements('phone').val();
// Neither phone2 and phone are valid?
if (!value && !phone) {
return false;
}
// phone2 is valid. Update validity of phone.
validator.updateStatus('phone', validator.STATUS_VALID);
return true;
},
message: 'at least one phone number is required'
}
}
}
}

backbone model sets value on false validate

I'm learning backbone.js and trying to figure out how to use the validation method. But my problem is when I call for validation the validation is triggered but it still saves the invalid data. As seen here player.set('firstName', '', { validate: true }); I set lastName variable to '' and it saves that values, and it shouldn't.
Edit - Updated code so now it works correctly
Backbone model.
var Player = Backbone.Model.extend({
defaults: {
firstName: "Not specified",
lastName: "Not specified",
position: "Not specified"
},
validate: function (attributes) {
// validate first name
if (!attributes.firstName || attributes.firstName === '') {
return 'you must have a first name';
}
// validate last name
if (!attributes.lastName || attributes.lastName === '') {
return 'you must provide a last name.';
}
// validate position
if (!attributes.position || attributes.position === '') {
return 'you must provide a position.';
}
},
initialize: function () {
// checks when firstName has changed
this.on('change:firstName', function () {
console.log("firstName attribute has changed.");
});
// checks when lastName has changed
this.on('change:lastName', function () {
console.log("lastName attribute has changed.");
});
// checks when position has changed
this.on('change:position', function () {
console.log("position attribute has changed.");
});
// check for valid inputs
this.on('error', function (model, error) {
console.log(error);
});
}
});
From within chrome dev tools I do the following code.
var player = new Player;
player.set({ firstName: "peter", lastName: "andrews", position: "outfield" }, { validate: true });
player.toJSON();
firstName attribute has changed. app.js:32
lastName attribute has changed. app.js:36
position attribute has changed. app.js:40
Object {firstName: "peter", lastName: "andrews", position: "outfield"}
player.set('firstName', '', { validate: true });
player.toJSON();
you must have a first name app.js:14
Object {firstName: "peter", lastName: "andrews", position: "outfield"}
From the Backbone docs:
If the attributes are valid, don't return anything from validate; if
they are invalid, return an error of your choosing.
Your validation function is printing the error strings with console.log but not returning anything.
Try changing your validate function to something like:
validate: function (attributes) {
// validate first name
if (!attributes.firstName || attributes.firstName === '') {
return 'you must have a first name';
}
// validate last name
if (!attributes.lastName || attributes.lastName === '') {
return 'you must provide a last name.';
}
// validate position
if (!attributes.position || attributes.position === '') {
return 'you must provide a position.';
}
},

Categories

Resources