简体   繁体   中英

JS: How to enable submit button in form only if all inputs pass validation

I have a simple input that I'm using an keyup event listener on. If the input length is too short, the span element will remove the class on it that hides the element and display "Input too short".

If I have multiple inputs, how can I only enable the Submit button if all fields pass the validation.
Unfortunately, I'm thinking in a React-way and would accomplish this via state.

<style type="text/css">
    .hide-first {
        display: none;
    }

    .hide-last {
        display: none;
    }
</style>
<div>
    <div>
        <input id="first-name" />
        <span id="validation-span" class="hide-first">Input too short</span>
    </div>
    <button>Submit</button>
</div>
<script type="text/javascript">
    let firstName = document.getElementById( 'first-name' );
    let span = document.getElementById( 'validation-span' );

    firstName.addEventListener( 'keyup', () => {
        console.log( event.target.value.length )
        if ( event.target.value.length < 5 ) {
            span.classList.remove( 'hide-first' )
        } else {
            span.classList.add( 'hide-first' )
        }
    } );
</script>

All your inputs could call the same validation function that checks everything except inputs that are empty. Only show the submit button if they all succeed and show the appropriate message on inputs that fail the validation.

Pseudo-code:

   boolean succes = true
   if username is invalid and not empty
      username invalid message
      success = false
   if password is invalid and not empty
      password invalid message
      success = false

   if success is true
       show submit button

Simple logic. Make a function that checks if all of the fields are validated, and call it from within the onkeyup event. A seemingly straight-forward way would be like this:

let firstName = document.getElementById('first-name'),
    lastName = document.getElementById('last-name'),
    company = document.getElementById('company-name');
let span = document.getElementById('validation-span'),
    span1 = document.getElementById('validation-span1'), 
    span2 = document.getElementById('validation-span2'), 
    conditions = [],
    length = 3;

firstName.addEventListener('keyup', () => {
    console.log(event.target.value.length)
    if (event.target.value.length < 5) {
        span.classList.remove('hide-first')
        conditions[0] = true;
    } else {
        span.classList.add('hide-first')
        conditions[0] = false;
    }
}) 

lastName.addEventListener('keyup', () => {
    console.log(event.target.value.length)
    if (event.target.value.length < 5) {
        span1.classList.remove('hide-first')
        conditions[1] = true;
    } else {
        span1.classList.add('hide-first')
        conditions[1] = false;
    }
})

company.addEventListener('keyup', () => {
    console.log(event.target.value.length)
    if (event.target.value.length < 5) {
        span2.classList.remove('hide-first')
        conditions[2] = true;
    } else {
        span2.classList.add('hide-first')
        conditions[2] = false;
    }
})

function checkAllTrueAndActivateSubmitBtn() {
    var result = true;
    for(var i = 0; i < length; i++) {
        if(!conditions[i]) {
            result = false;
        }
    }
    if(result) {
        submitBtn.classList.add("shown"); //or whatever
    }
}

but of course, the more fields you have,the more messy this becomes. A more efficient way would be to use an array for the fields, and conditions:

let IDsAndConditions = {
    'first-name':{
        condition: (x) => x.length >= 5,
        span: 'validation-span'
    },
    'last-name': {
        condition: (x) => x.length >= 8,
        span: 'validation-span-lastName'
    },
    'phoneNumber':{
        condition: (x) => x.match(/^-{0,1}\d+$/),//or whatever
        span:"phone-span"
    }
};
var conditions = [];
var num = 0;
for(var k in IDsAndConditions) {
    var cur = IDsAndConditions[k];
    var el = document.getElementById(k);
    var span = document.getElementById(cur["span"]);
    if(el && span) {
        el.addEventListener('keyup', () => {
            console.log(event.target.value.length)
            if (!cur["condition"](event.target.value)) {
                span.classList.remove('hide-first')
                conditions[num] = true;
            } else {
                span.classList.add('hide-first')
                conditions[num] = false;
            }
            checkAllTrueAndActivateSubmitBtn();
        });

    } else {
        conditions[num] = true; //this is to make the validation work even if the element doesn't exist
    }
    num++;
}



function checkAllTrueAndActivateSubmitBtn() {
    var result = true;
    for(var i = 0; i < IDsAndConditions.length; i++) {
        if(!conditions[i]) {
            result = false;
        }
    }
    if(result) {
        submitBtn.classList.add("active"); //or whatever
    } else {
        submitBtn.classList.remove("active"); //even if it was active at one point, if someone changes a field to an incorrect value, it deactivates again
    }
}

Something like this should work

<div>
    <div>
        <input id="first-name" onchange='validation()'/>
        <span id ="validation-span" class="hide-first">Input too short</span>
    </div>
    <button id='submit-button'>
        Submit
    </button>
</div>

<script type="text/javascript">
    function validateFirstName() {
        let firstName = document.getElementById('first-name');
        let span = document.getElementById('validation-span');
        if (event.target.value.length < 5) {
            span.classList.remove('hide-first')
            return True
        }
        span.classList.add('hide-first')
        return False
     }

    function validation() {
         let submitButton = document.getElementById('submit-button');
         submitButton.disabled = validateFirstName(); 
    }
</script>

As you add additional fields, you should create the validation function for that field, and then running it inside validation() like:

function validation() {
    let submitButton = document.getElementById('submit-button');
    submitButton.disabled = validateFirstName() && validateSecondField() && validateThirdField() &&...;
}

Remember to add to the html input the onchange event listener.

At first add style your button style="display:none" . You can use jQuery as bellow

$( document ).ready( function () {
    var _rules = {
        "first-name": function ( $owner ) {
            var val = $owner.val();
            if ( !val ) return false;
            if ( val.length < 5 ) return false;
            return true;
        }
    };
    //Validate here
    function validate(total_mark) {
        var mark = 0;//total mark
        //Read all input value, than check rules
        $( 'input' ).each( function () {
            if ( 'function' !== typeof ( _rules[this.id] ) ) return;
            var $owner = $( this );
            var result = _rules[this.id]( $owner );
            if ( !result ) {
                mark -= 1;
                $owner.next().removeClass( 'hide-first' );
                return;
            }
            $owner.next().addClass( 'hide-first' );
            mark += 1;
            return;
        } );
        return mark;
    };
    var $btn = $( 'button' );
    //Register keyup event for all input
    var total_input = 1;
    $( 'input' ).on( "keyup", function ( e ) {
        e.preventDefault();
        $btn.css( "display", "none" );
        if ( validate() < total_input ) return;
        $btn.css( "display", "" );
    } );
} );

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM