admin管理员组

文章数量:1290265

Working on a set_password.js ponent that, you guessed it, lets the user set their password. It has them enter it twice to make sure they match. The password should have the criteria that it is at least 8 characters in length, has one uppercase, has one number, has one special character. Nothing ground breaking.

I know how to validate this stuff server side, but would rather validate it client side so the user doesn't have to wait for server response. I am struggling with how to do it.

I have a validate function that takes the values from the fields and validates them.

function validate(values) {
    const errors = {};

    if (!values.password1) {
        errors.password1 = 'This field cannot be empty.'
    }
    if (!values.password2) {
        errors.password2 = 'This field cannot be empty.'
    }
    if (values.password1.length < 8) {
         errors.password1 = 'The password provided is not long enough.'
    }
    if (values.password2.length < 8) {
         errors.password2 = 'The password provided is not long enough.'
    }
    return errors
}

This is all I have so far, and I get an error Cannot read property 'length' of undefined, so I am apparently putting this logic in the wrong area.

I'm starting to think that I should put it in the action so it is validated only after the user does onSubmit. I guess it would look something like:

onSubmit(values) {
    this.props.setPassword(values, this.props.match.params);  
}

export function setPassword({ password1, password2 }, { id, key }) {
    return function(dispatch) {
        if (password1.length < 8 && password2.length < 8) {
            axios
                .post(
                    `${ROOT_URL}/api/auth/set_password/`, 
                    { password1, password2, id, key }
                )
                .then(response => {
                    console.log('Password changed')
                })
                .catch(error => {        
                    dispatch(authError(error.response.data.non_field_errors[0]));
        });
        }

    }
}

Anyway, so what is the correct way to acplish this? Checking length of string, that it has at least one uppercase letter, that is has one special character, and one number?

EDIT:

Relevant form data:

// This renders errors regarding the form inputs
    renderField(field) {
        const { 
            label, 
            type,
            name,
            meta: {
                touched, 
                error 
            } 
        } = field;

        return (
            <div className='form-group'>
                <label>{label}</label>
                <input 
                    className='form-control' 
                    type={type}
                    placeholder={label}
                    {...field.input} 
                />
                <div className='text-danger'>
                    {touched ? error : ""}
                </div>
            </div>
        );
    }

    // The main body to be rendered
    render() {
        if (this.props.permitRender) {
            const { handleSubmit } = this.props;
            return (
                <div>

                    <h3>Set New Password</h3>
                    <p>Type your new password twice. </p>
                    <p>It must be a minimum of 8 characters in length and contain at least:</p>
                    <ol>
                        <li>One uppercase character</li>
                        <li>One special character</li>
                        <li>One number</li>
                    </ol>

                    <form onSubmit={handleSubmit(this.onSubmit.bind(this))}>
                        {this.renderAlert()}
                        <Field 
                            label='Enter New Password'
                            name='password1'
                            type='password'
                            ponent={this.renderField} 
                        />
                        <Field 
                            label='Confirm New Password'
                            name='password2'
                            type='password'
                            ponent={this.renderField} 
                        />
                        <button type="submit" className="btn btn-primary">Submit</button>
                    </form>
                </div>
            );            
        } else if (!this.props.permitRender) {
            return ( 
                <div> { this.renderAlert() } </div>
            );
        } 
    }

Working on a set_password.js ponent that, you guessed it, lets the user set their password. It has them enter it twice to make sure they match. The password should have the criteria that it is at least 8 characters in length, has one uppercase, has one number, has one special character. Nothing ground breaking.

I know how to validate this stuff server side, but would rather validate it client side so the user doesn't have to wait for server response. I am struggling with how to do it.

I have a validate function that takes the values from the fields and validates them.

function validate(values) {
    const errors = {};

    if (!values.password1) {
        errors.password1 = 'This field cannot be empty.'
    }
    if (!values.password2) {
        errors.password2 = 'This field cannot be empty.'
    }
    if (values.password1.length < 8) {
         errors.password1 = 'The password provided is not long enough.'
    }
    if (values.password2.length < 8) {
         errors.password2 = 'The password provided is not long enough.'
    }
    return errors
}

This is all I have so far, and I get an error Cannot read property 'length' of undefined, so I am apparently putting this logic in the wrong area.

I'm starting to think that I should put it in the action so it is validated only after the user does onSubmit. I guess it would look something like:

onSubmit(values) {
    this.props.setPassword(values, this.props.match.params);  
}

export function setPassword({ password1, password2 }, { id, key }) {
    return function(dispatch) {
        if (password1.length < 8 && password2.length < 8) {
            axios
                .post(
                    `${ROOT_URL}/api/auth/set_password/`, 
                    { password1, password2, id, key }
                )
                .then(response => {
                    console.log('Password changed')
                })
                .catch(error => {        
                    dispatch(authError(error.response.data.non_field_errors[0]));
        });
        }

    }
}

Anyway, so what is the correct way to acplish this? Checking length of string, that it has at least one uppercase letter, that is has one special character, and one number?

EDIT:

Relevant form data:

// This renders errors regarding the form inputs
    renderField(field) {
        const { 
            label, 
            type,
            name,
            meta: {
                touched, 
                error 
            } 
        } = field;

        return (
            <div className='form-group'>
                <label>{label}</label>
                <input 
                    className='form-control' 
                    type={type}
                    placeholder={label}
                    {...field.input} 
                />
                <div className='text-danger'>
                    {touched ? error : ""}
                </div>
            </div>
        );
    }

    // The main body to be rendered
    render() {
        if (this.props.permitRender) {
            const { handleSubmit } = this.props;
            return (
                <div>

                    <h3>Set New Password</h3>
                    <p>Type your new password twice. </p>
                    <p>It must be a minimum of 8 characters in length and contain at least:</p>
                    <ol>
                        <li>One uppercase character</li>
                        <li>One special character</li>
                        <li>One number</li>
                    </ol>

                    <form onSubmit={handleSubmit(this.onSubmit.bind(this))}>
                        {this.renderAlert()}
                        <Field 
                            label='Enter New Password'
                            name='password1'
                            type='password'
                            ponent={this.renderField} 
                        />
                        <Field 
                            label='Confirm New Password'
                            name='password2'
                            type='password'
                            ponent={this.renderField} 
                        />
                        <button type="submit" className="btn btn-primary">Submit</button>
                    </form>
                </div>
            );            
        } else if (!this.props.permitRender) {
            return ( 
                <div> { this.renderAlert() } </div>
            );
        } 
    }
Share Improve this question edited Oct 6, 2017 at 15:22 cheslijones asked Oct 5, 2017 at 22:56 cheslijonescheslijones 9,19424 gold badges99 silver badges208 bronze badges 3
  • I strongly remend using the jQuery Validation Plugin. – Nick Cordova Commented Oct 5, 2017 at 23:03
  • Can you post relevant part of your form with the password fields? – Dario Commented Oct 6, 2017 at 6:13
  • Ok added the form data. – cheslijones Commented Oct 6, 2017 at 15:23
Add a ment  | 

2 Answers 2

Reset to default 4

Right now, your validating if-statements are ordered somewhat wrongly. I don't think you can just assume any of the password values are set anyway.
It'd probably be better to first do a null-check on the string you want to validate, and only after that do the length- and character check.

The validation of what characters should be in there can probably be done by using one (or more, which is probably easier) regex patterns.

// null check
if (!values.password1) {
    errors.password1 = 'This field cannot be empty.'
}
// After null checking, check length
else if (values.password1.length < 8) {
     errors.password1 = 'The password provided is not long enough.'
}
// Check for capital letters
else if (/([A-Z]+)/g.test(values.password1) {
     errors.password1 = 'You don\'t have any capital letters in there yo'
}

// Same here as before, pretty much
if (!values.password2) {
    errors.password2 = 'This field cannot be empty.'
}
else if (values.password2.length < 8) {
     errors.password2 = 'The password provided is not long enough.'
}

You can also do something like values.password1 && values.password1.length > 8 in your if statements to do each null check seperately.

https://regex101./ is a good place to try out and experiment with regex patterns if you do go that route.

I'm running into a similar issue with handling a form submit with two different text inputs, but the user can be optionally add text to one or the other. I also found it a little frustrating that something like myString.length seems to work if they entered text, but break the logic otherwise? If you're ok with adding a library,

I'm going to change my logic from

if (myString.length == 0){
    //do stuff
 } 

to the LoDash _.isEmpty method. This will look more like

if(_.isEmpty(myString)) {
   //do stuff...
  }

LoDash docs for isEmpty Method <-- I use this all the time as it works for strings, arrays, objects etc...Hope this helps someone else!

本文标签: