Build validation using VanillaJS for Form Submit

Xây dựng bắt lỗi form bằng VanillaJS để gửi biểu mẫu


Chuẩn bị:

- VSCode
- Kiến thức HTML/CSS/JS

Để bắt lỗi form trước khi gửi tới server xử lý ta làm như sau:

Cấu trúc source:

Tập chung vào các file sau:
- Common.js: xây dựng các hàm global sử dụng nhiều lần
- Validation.js: xây dựng các hàm bắt lỗi trong đối tượng Validation
- Main.js: xử lý dữ liệu được lấy từ form để submit

Giao diện được xây dựng:
Form:

Thông báo:

file index.html
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Java Doc Fast</title>
    <link rel="stylesheet" href="assets/css/styles.css">
</head>
<body>
    <form action="success.html" method="GET">
        <table>
            <tr>
                <th>Tài khoản:</th>
                <td><input type="text" name="username" id="username"></td>
                <td><span id="errorUsername"></span></td>
            </tr>
            <tr>
                <th>Họ và tên:</th>
                <td><input type="text" name="fullName" id="fullName"></td>
                <td><span id="errorFullName"></span></td>
            </tr>
            <tr>
                <th>Email:</th>
                <td><input type="text" name="email" id="email"></td>
                <td><span id="errorEmail"></span></td>
            </tr>
            <tr>
                <th>Mật khẩu:</th>
                <td><input type="password" name="password" id="password" autocomplete></td>
                <td><span id="errorPassword"></span></td>
            </tr>
            <tr>
                <th>Xác Nhận Mật khẩu:</th>
                <td><input type="password" name="retryPassword" id="retryPassword" autocomplete></td>
                <td><span id="errorRetryPassword"></span></td>
            </tr>
            <tr>
                <th>Ngày bắt đầu làm:</th>
                <td><input type="date" name="startDate" id="startDate"></td>
                <td><span id="errorStartDate"></span></td>
            </tr>
            <tr>
                <th>Lương cơ bản:</th>
                <td><input type="text" name="salary" id="salary"></td>
                <td><span id="errorSalary"></span></td>
            </tr>
            <tr>
                <th>Chức vụ:</th>
                <td>
                    <select name="position" id="position">
                        <option value="">--- Chọn ---</option>
                        <option value="0">Giám đốc</option>
                        <option value="1">Trưởng phòng</option>
                        <option value="2">Nhân viên</option>
                    </select>
                </td>
                <td><span id="errorPosition"></span></td>
            </tr>
            <tr>
                <th>Sở thích:</th>
                <td>
                    <input type="checkbox" name="hobbies" value="Coder">Coder &nbsp;
                    <input type="checkbox" name="hobbies" value="Đọc sách">Đọc sách &nbsp;
                    <input type="checkbox" name="hobbies" value="Thể thao">Thể thao
                </td>
                <td><span id="errorHobbies"></span></td>
            </tr>
            <tr>
                <th>Giờ làm:</th>
                <td><input type="text" name="workTime" id="workTime"></td>
                <td><span id="errorWorkTime"></span></td>
            </tr>
            <tr>
                <th></th>
                <td><button type="submit" id="btnSubmit">Xác nhận</button></td>
            </tr>
        </table>
    </form>

    <script src="assets/js/Common.js"></script>
    <script src="assets/js/Validation.js"></script>
    <script src="assets/js/Main.js"></script>
</body>
</html>

file success.html
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Java Doc Fast</title>
</head>
<body>
    <h1>Thành công!</h1>
</body>
</html>

file styles.css
th {
    text-alignleft;
}

Giao diện xảy ra lỗi được xây dựng:


file Common.js
// Tạo hàm getElement cho ngắn gọn
function getElement(id) {
    return document.getElementById(id);
}

// Tạo hàm querySelectorAll cho ngắn gọn
function querySelectorAll(selector) {
    return document.querySelectorAll(selector);
}

file Validation.js
function Validation() {

    // Hàm kiểm tra rỗng
    this.isBlank = function (inputidmsg) {
        if (!Object.is('', input.trim())) {
            getElement(id).innerHTML = '';
            return true;
        }
        getElement(id).innerHTML = msg;
        getElement(id).style.color = 'red';
        return false;
    }
    
    // Hàm check độ dài từ min - max 
    this.isLength = function (inputidmsgminmax) {
        if (input.length >= min && input.length <= max) {
            getElement(id).innerHTML = '';
            return true;
        }
        getElement(id).innerHTML = msg;
        getElement(id).style.color = 'red';
        return false;
    };

    // Hàm kiểm tra Tiếng Việt
    this.isVietnamese = function (inputidmsg) {
        var pattern = 
            '^[a-zA-Z_ÀÁÂÃÈÉÊẾÌÍÒÓÔÕÙÚĂĐĨŨƠàáâãèéêìíòóôõùúăđĩũơƯĂẠẢẤẦẨẪẬẮẰẲẴẶ' +
            'ẸẺẼỀỀỂưăạảấầẩẫậắằẳẵặẹẻẽềềểếỄỆỈỊỌỎỐỒỔỖỘỚỜỞỠỢỤỦỨỪễệỉịọỏốồổỗộớờởỡợ' +
            'ụủứừỬỮỰỲỴÝỶỸửữựỳỵỷỹ\\s]+$';
        if (input.match(pattern)) {
            getElement(id).innerHTML = '';
            return true;
        }
        getElement(id).innerHTML = msg;
        getElement(id).style.color = 'red';
        return false;
    };

    // Hàm kiểm tra Email
    this.isEmail = function(inputidmsg) {
        var pattern = '^\\w{1,}@\\w{2,}(\\.\\w{2,}){1,2}$';
        if (input.match(pattern)) {
            getElement(id).innerHTML = '';
            return true;
        }
        getElement(id).innerHTML = msg;
        getElement(id).style.color = 'red';
        return false;
    };

    // Hàm kiểm tra mật khẩu: (chứa ít nhất 1 ký tự số, 1 ký tự in hoa, 1 ký tự đặc biệt)
    this.isPasssword = function (inputidmsg) {
        var pattern = '^(?=.*\\d)(?=.*[a-z])(?=.*[A-Z])(?=.*[@$!%*#?&])[0-9a-zA-Z@$!%*#?&\\s]+$';
        if (input.match(pattern)) {
            getElement(id).innerHTML = '';
            return true;
        }
        getElement(id).innerHTML = msg;
        getElement(id).style.color = 'red';
        return false;
    };

    // Hàm kiểm tra xác nhận mật khẩu
    this.isRetryPasssword = function (inputretryInputidmsg) {
        if (Object.is(inputretryInput)) {
            getElement(id).innerHTML = '';
            return true;
        }
        getElement(id).innerHTML = msg;
        getElement(id).style.color = 'red';
        return false;
    };

    // Hàm kiểm tra MM/dd/yyyy
    // Tips: dd/MM/yyyy: ^((0?[1-9]|[12][0-9]|3[01])[/](0?[1-9]|1[012])[/](19|20)?[0-9]{2})*$
    // Tips: yyyy/MM/dd: ^((19|20)?[0-9]{2}[/](0?[1-9]|[12][0-9]|3[01])[/](0?[1-9]|1[012]))*$
    // Tips: thay / -> - để có yyyy/MM/dd -> yyyy-MM-dd
    this.isDateMMddyyyy = function (inputidmsg) {
        var pattern = '^((0?[1-9]|1[012])[/](0?[1-9]|[12][0-9]|3[01])[/](19|20)?[0-9]{2})*$';
        if (input.match(pattern)) {
            getElement(id).innerHTML = '';
            return true;
        }
        getElement(id).innerHTML = msg;
        getElement(id).style.color = 'red';
        return false;
    };

    // Hàm kiểm tra number
    this.isNumber = function(inputidmsg) {
        var pattern = '^[+-]?([0-9]*[\\.])?[0-9]+$';
        if (input.match(pattern)) {
            getElement(id).innerHTML = '';
            return true;
        }
        getElement(id).innerHTML = msg;
        getElement(id).style.color = 'red';
        return false;
    };

    // Hàm kiểm tra giá trị
    this.isValue = function(inputidmsgminmax) {
        if (input >= min && input <= max) {
            getElement(id).innerHTML = '';
            return true;
        }
        getElement(id).innerHTML = msg;
        getElement(id).style.color = 'red';
        return false;
    };

    // Hàm kiểm tra regex
    this.isRegex = function(inputidmsgregex) {
        if (input.match(regex)) {
            getElement(id).innerHTML = '';
            return true;
        }
        getElement(id).innerHTML = msg;
        getElement(id).style.color = 'red';
        return false;
    };

    // Hàm kiểm tra select có điều kiện
    this.isSelected = function(inputidmsgcondition) {
        if(!Object.is(conditioninput)) {
            getElement(id).innerHTML = '';
            return true;
        }
        getElement(id).innerHTML = msg;
        getElement(id).style.color = 'red';
        return false;
    }

    // Hàm kiểm tra checkbox
    this.isChecked = function(inputidmsg) {
        if(!Object.is(0, input.length)) {
            getElement(id).innerHTML = '';
            return true;
        }
        getElement(id).innerHTML = msg;
        getElement(id).style.color = 'red';
        return false;
    }

}

file Main.js
// Tạo đối tượng Validation để sử dụng
var validation = new Validation();

// Hàm validate các dữ liệu trong form
function validateForm() {

    // Khai báo các biến và get value từ form
    var username = getElement('username').value;
    var fullName = getElement('fullName').value;
    var email = getElement('email').value;
    var password = getElement('password').value;
    var retryPassword = getElement('retryPassword').value;
    var startDate = getElement('startDate').value;
    var salary = getElement('salary').value;
    var position = getElement('position').value;
    var workTime = getElement('workTime').value;
    var hobbies = querySelectorAll('input[name="hobbies"]:checked');

    // Tạo biến isValid để kiểm tra lỗi
    var isValid = true;

    // Kiểm tra username: Tài khoản tối đa 4 - 6 ký số, không để trống
    isValid &=
        validation.isBlank(username'errorUsername''(*) Tài khoản không để trống') &&
        validation.isLength(username'errorUsername''(*) Tài khoản tối đa 4 - 6 ký số'46);
    
    // Kiểm tra fullName: Họ tên phải là chữ, không để trống
    isValid &=
        validation.isBlank(fullName'errorFullName''(*) Họ tên không để trống') &&
        validation.isLength(fullName'errorFullName''(*) Họ tên tối đa 4 - 20 ký tự'420) &&
        validation.isVietnamese(fullName'errorFullName''(*) Họ tên phải là chữ');

    // Kiểm tra email: Email phải đúng định dạng, không để trống
    isValid &=
        validation.isBlank(email'errorEmail''(*) Email không để trống') &&
        validation.isEmail(email'errorEmail''(*) Email không đúng định dạng');
    
    // Kiểm tra password: Mật khẩu từ 6-10 ký tự (chứa ít nhất 1 ký tự số, 1 ký tự in hoa, 1 ký tự đặc biệt), không để trống
    isValid &=
        validation.isBlank(password'errorPassword''(*) Mật khẩu không để trống') &&
        validation.isLength(password'errorPassword''(*) Mật khẩu tối đa 6 - 10 ký tự'610) &&
        validation.isPasssword(password'errorPassword''(*) Mật khẩu chứa ít nhất 1 ký tự số, 1 ký tự in hoa, 1 ký tự đặc biệt');
    
    // Kiểm tra retryPassword: Mật khẩu xác nhận phải khớp
    isValid &=
        validation.isRetryPasssword(passwordretryPassword'errorRetryPassword''(*) Mật khẩu xác nhận không đúng');

    // Kiểm tra startDate: Ngày làm không để trống, định dạng mm/dd/yyyy
    isValid &=
        validation.isBlank(startDate'errorStartDate''(*) Ngày làm không để trống');

    // Kiểm tra salary: Lương cơ bản 1 000 000 - 20 000 000, không để trống, phải là số
    isValid &=
        validation.isBlank(salary'errorSalary''(*) Lương cơ bản không để trống') &&
        validation.isNumber(salary'errorSalary''(*) Lương cơ bản phải là số') && 
        validation.isValue(salary'errorSalary''(*) Lương cơ bản 1000000 - 20000000'1_000_00020_000_000);

    // Kiểm tra position: Chức vụ phải chọn chức vụ hợp lệ
    isValid &=
        // validation.isBlank(position, 'errorPosition', '(*) Chức vụ phải được chọn');
        validation.isSelected(position'errorPosition''(*) Chức vụ phải được chọn''');

    // Kiểm tra hobbies: Sở thích phải được chọn
    isValid &=
        validation.isChecked(hobbies'errorHobbies''(*) Sở thích phải được chọn');
    
    // Kiểm tra workTime: Số giờ làm trong tháng 80 - 200 giờ, không để trống
    isValid &=
        validation.isBlank(workTime'errorWorkTime''(*) Số giờ làm không để trống') &&
        // validation.isNumber(workTime, 'errorWorkTime', '(*) Số giờ làm phải là số') && 
        validation.isRegex(workTime'errorWorkTime''(*) Số giờ làm phải là số''^[+-]?([0-9]*[\\.])?[0-9]+$') && 
        validation.isValue(workTime'errorWorkTime''(*) Số giờ làm 80 - 200'80200);

    return isValid;
}

// Click submit
getElement('btnSubmit').addEventListener('click'function(event) {

    if(!validateForm()) {
        event.preventDefault();
    }

});

Muốn lỗi hiển thị như giao diện trên ta cần thêm vào HTML các đoạn code sau:
<span id="errorUsername"></span>
<span id="errorFullName"></span>
<span id="errorEmail"></span>
<span id="errorPassword"></span>
<span id="errorRetryPassword"></span>
<span id="errorStartDate"></span>
<span id="errorSalary"></span>
<span id="errorPosition"></span>
<span id="errorHobbies"></span>
<span id="errorWorkTime"></span>

Full code:

Nhận xét

Bài đăng phổ biến từ blog này

Java EE Web Application (JSP/Servlet, EJB, JPA, SQL Server, Glassfish) Full Tutorial

Java EE Web Application (JavaServer Faces, EJB, JPA, SQL Server, Glassfish) Full Tutorial