1

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>
Rajib Chy
  • 800
  • 10
  • 22
Raymon Opie
  • 237
  • 1
  • 9
  • Where are your other inputs? Does all follow the same rule? – mrReiha Jan 24 '19 at 01:56
  • @mrReiha I haven't added it yet. They will have different rules but just regex rules. – Raymon Opie Jan 24 '19 at 02:02
  • @RaymonOpie you probably should use `onChange` better than `onKeyUp`. See: https://stackoverflow.com/questions/574941/best-way-to-track-onchange-as-you-type-in-input-type-text – spaniard Jan 24 '19 at 02:07
  • Basically, this is what you should go through. define a variable ( called `stateHolder` for example ) which will hold the state of form ( valid/invalid ) and start a loop for all of your inputs. you can fill this variable with `false` once validation function didn't work and at the end, you should show button only if that `stateHolder` had `true`. – mrReiha Jan 24 '19 at 02:15

4 Answers4

0

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
Joe Degiovanni
  • 205
  • 4
  • 6
Word Rearranger
  • 1,306
  • 1
  • 16
  • 25
0

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
    }
}
0

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.

spaniard
  • 541
  • 2
  • 12
0

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", "" );
    } );
} );
Rajib Chy
  • 800
  • 10
  • 22