DEV Community

Discussion on: Form validation using javascript

Collapse
 
rkallan profile image
RRKallan

I understand your explanation and I can agree about the static validation as a start

But to get the values of your form elements I would suggest to use event.currentTarget.elements

The 2 functions setError and setSucces I would created as 1 function

const setValidationClassName = (element, isValid = true, message = ‘’) => {
    const inputControl = element.parentElement;
    const errorDisplay = inputControl.querySelector('.error');
    const validationClassNames = [error, succes];

    errorDisplay.innerText = message;
    inputControl.classList.replace(validationClassNames[!isValid], validationClassNames[isValid]);
}
Enter fullscreen mode Exit fullscreen mode

The if statements for validation I would created functions. And avoiding if elseif else statements
And return value would be a object

return {
    isValid: true,
    message: ‘’,
};
Enter fullscreen mode Exit fullscreen mode
Thread Thread
 
anil027 profile image
Anil Kumar Venugopal

Hi RRKallan,Thanks for explaining this, can you provide real time working example on the same !!

Thread Thread
 
rkallan profile image
RRKallan

@anil027

<div class="container">
    <form id="form" action="/" method="post" novalidate>
        <h1>Registration</h1>
        <div class="input-control">
            <label for="username">Username</label>
            <input id="username" name="username" type="text" required data-validation="username" />
            <div class="error"></div>
        </div>
        <div class="input-control">
            <label for="email">Email</label>
            <input id="email" name="email" type="email" required data-validation="email" />
            <div class="error"></div>
        </div>
        <div class="input-control">
            <label for="password">Password</label>
            <input id="password" name="password" type="password" required data-validation="password" />
            <div class="error"></div>
        </div>
        <div class="input-control">
            <label for="password2">Password again</label>
            <input id="password2" name="password2" type="password" required data-validation="passwordConfirm" />
            <div class="error"></div>
        </div>
        <button type="submit">Sign Up</button>
    </form>
</div>
Enter fullscreen mode Exit fullscreen mode
const getType = (value) => {
    const type = Object.prototype.toString.call(value).slice(1, -1).split(" ");

    return type && type[1].toLowerCase();
};

const validations = {
    isEmpty: ({ value }) => {
        const valueIsType = getType(value);

        if (valueIsType === "string") return !value.trim().length;
        if (valueIsType === "array") return !value.length;
        if (valueIsType === "object") return !Object.keys(value).length;
        if (valueIsType === "number") return Number.isNaN(value);
        if (valueIsType === "boolean") return false;

        return true;
    },
    email: ({ value }) => {
        const isEmpty = validations.isEmpty({ value });
        const returnValue = {
            isValid: false,
            message: null,
        };

        if (isEmpty === true) {
            returnValue.message = "Email is required";
            return returnValue;
        }

        const pattern =
            /^(([^<>()[\]\\.,;:\s@"]+(\.[^<>()[\]\\.,;:\s@"]+)*)|(".+"))@((\[[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}])|(([a-zA-Z\-0-9]+\.)+[a-zA-Z]{2,}))$/;
        const isValid = pattern.test(String(value).toLowerCase());

        if (isValid === false) {
            returnValue.message = "Provide a valid email address";
        }
        returnValue.isValid = isValid;

        return returnValue;
    },
    username: ({ value }) => {
        const isEmpty = validations.isEmpty({ value });
        const returnValue = {
            isValid: !isEmpty,
            message: null,
        };

        if (isEmpty === true) {
            returnValue.message = "Username is required";
        }
        return returnValue;
    },
    password: ({ value }) => {
        const isEmpty = validations.isEmpty({ value });
        const returnValue = {
            isValid: false,
            message: null,
        };

        if (isEmpty === true) {
            returnValue.message = "Password is required";
            return returnValue;
        }

        if (value.length < 8) {
            returnValue.message = "Password must be at least 8 character.";
            return returnValue;
        }

        returnValue.isValid = true;
        return returnValue;
    },
    passwordConfirm: ({ value, valueToMatch }) => {
        const isEmpty = validations.isEmpty({ value });
        const valueToMatchIsEmpty = validations.isEmpty(valueToMatch);
        const returnValue = {
            isValid: false,
            message: null,
        };

        if (valueToMatchIsEmpty === true) {
            return returnValue;
        }

        if (isEmpty === true) {
            returnValue.message = "Please confirm your password";
            return returnValue;
        }

        if (value !== valueToMatch) {
            returnValue.message = "Passwords doesn't match";
            return returnValue;
        }

        returnValue.isValid = true;
        return returnValue;
    },
};

const setInputControlClassName = ({ element, isValid = true, message = null }) => {
    const inputControl = element.parentElement || {};
    inputControl.classList.toggle("error", !isValid);
    inputControl.classList.toggle("succes", isValid);

    const errorDisplay = inputControl.querySelector(".error") || {};
    errorDisplay.innerText = message || "";
};

const onSubmitForm = (event) => {
    event.preventDefault();

    const formObject = event.currentTarget;
    const formElements = formObject.elements;

    Array.prototype.slice.call(formElements).forEach((element) => {
        const { type, required, dataset } = element;

        if (["submit", "reset", "button"].includes(type) || !required) return;

        const validationType = dataset.validation;
        const value = element.value?.trim();
        const valueToMatch = validationType === "passwordConfirm" ? formElements.password?.value?.trim() : null;
        const { isValid, message } = validations[validationType]({ value, valueToMatch });

        setInputControlClassName({ element, isValid, message });
    });
};

const formElement = document.querySelector("#form");
formElement.addEventListener("submit", onSubmitForm);
Enter fullscreen mode Exit fullscreen mode
Thread Thread
 
anil027 profile image
Anil Kumar Venugopal

Thank you !!