Wednesday, January 31, 2018

Control statement for removing attributes and classes having opposite effect

Leave a Comment

I'm building a registration page and I want the button to be disabled until all of the inputs pass validation. Well I have all of the native validation logic done (missing values, pattern mismatch, etc...), but I wanted to implement a "username taken/available" piece of validation where the button still wouldn't be enabled until the username had valid inputs for all of their inputs AND supplied a desired username that was not already in use.
I have the server call and all of that all done, my only issue is the actual enabling/disabling of the button and assigning the border classes to the inputs. Here is my code for the response from the AJAX call:

ajax.onload = function() {     if (this.responseText === "taken") {         if (username.classList.contains("taken")) {             return;         } else {             username.classList.remove("successBorder");             username.classList.add("errorBorder");             username.classList.add("taken");         }     } else {         if (!username.checkValidity()) {             username.classList.remove("successBorder");             username.classList.add("errorBorder");             return;         } else {             username.classList.remove("errorBorder");             username.classList.add("successBorder");             username.classList.remove("taken");         }     } } 

And then here is the code for where the button is enabled/disabled that is called on the input event for every input element:

function validate() {      if (document.querySelector("form").checkValidity() && !(username.classList.contains("taken"))) {         registerButton.removeAttribute("disabled");         const ruleSpans = document.querySelectorAll("span[data-rule]");         for (span of ruleSpans) {             span.classList.add("hide");         }         for (input of inputs) {             input.classList.remove("errorBorder");             input.classList.add("successBorder");         }         return;     }      registerButton.setAttribute("disabled", "true");      if (this.checkValidity()) {     // Get rid of the error messages         this.classList.remove("errorBorder");         this.classList.add("successBorder");         const ruleSpans = document.getElementsByClassName(this.id);         for (span of ruleSpans) {             span.classList.add("hide");         }         return;     }  // Adding attention borders and error messages based upon what the issue is     this.classList.remove("successBorder");     this.classList.add("errorBorder");     const ruleSpans = document.getElementsByClassName(this.id);     for (span of ruleSpans) {         span.classList.add("hide");         switch (span.getAttribute("data-rule")) {             case "patternMismatch":                 if (this.validity.patternMismatch) {                     span.classList.remove("hide");                 }                    break;             case "valueMissing":                 if (this.validity.valueMissing) {                     span.classList.remove("hide");                 }                 break;             case "typeMismatch":                 if (this.validity.typeMismatch) {                     span.classList.remove("hide");                 }                 break;         }     } } 

And right now, the disabling/enabling works IF it's the first time on input for that element, but it is "behind" all of the times after the first time. (for example, if the username is taken, the register button is enabled, but if the username is taken, the register button is disabled, the exact opposite of what I want happening).
So I thought, instead of checking for it the correct way (the way I did it in the code !(username.classList.contains("taken"))), I would reverse the logic to look like this: username.classList.contains("taken"). And that works (even though it is logically wrong and incredibly hack-y), EXCEPT for the first time a taken username is had.
What am I doing logically wrong here?

2 Answers

Answers 1

I would suggest you to have a code structure like this

      function serverValidation () {         //make the ajax call here to validate all server validation         //send the success callback handler to 'clientValidations'     }     function clientValidations(){         //validate other form elements that does not require a server request here          //Then submit the form through an ajax form submit         submitFormThroughAjax();     }     function submitFormThroughAjax() {         //submit the form through ajax.     }     function onSubmit(event) {         event.preventDefault();         serverValidation();     }     //Here onSubmit should be attached to the form submit handler.  

Refer:below link to know how to submit a form through ajax.

https://developer.mozilla.org/en-US/docs/Web/API/XMLHttpRequest/Using_XMLHttpRequest

This example does all the validations only after the user submits but if you want the errors to be shown instantaneously as the user interacts you need to handle it through specific form element events.

Answers 2

You can directly assign the classes in CSS :invalid pseudo selector is available

If You Enjoyed This, Take 5 Seconds To Share It

0 comments:

Post a Comment