Form Validate

regexp | javascript

Прізвище

Може складатися з двох частин (Карпенко-Карий), які пишуться через дефіс

maxlength="30"
placeholder="Іваненко"
pattern="[А-яІіЇїЄєҐґ\-'’]{2,30}"
required

Ім’я

Може складатися з двох слів (Анна Марія), тому тут є пробіл

maxlength="30"
placeholder="Василь"
pattern="[А-яІіЇїЄєҐґ\s'’]{2,30}"
required

По батькові

maxlength="30"
placeholder="Федорович"
pattern="[А-яІіЇїЄєҐґ'’]{2,30}"

email

maxlength="50"
placeholder="name@example.com"
pattern="[0-9A-Z_a-z\.\-]+@[0-9A-Z_a-z\.\-]+?\.[a-z]{2,}"
required

Перевірити поля по шаблонам і піти на іншу сторінку або скрипт:

В form є action і onsubmit.

onsubmit - запускає bootstrap-перевірку полів, і якщо вона проходить - виконується action.

Поля з pattert - перевіряються по цьому шаблону, якщо у поля є тільки required - поле перевіряєтся на не порожність. Якщо нема ні того, ні іншого - поле не перевіряється.

HTML
<form id="mainform" action="user_login.py" method="POST" class="row g-3 needs-validation" novalidate onsubmit="is_valid();">
    <div class="col-md-4">
        <label for="login" class="form-label">{{ TX_LOGIN }}</label>
        <input type="text" class="form-control" id="login" name="login" aria-describedby="loginHelpBlock" pattern="^[\.@\d\-\A-Za-z]+$" required>
        <div id="loginHelpBlock" class="form-text">{{ TX_HELP_LOGIN }}</div>
        <div class="invalid-feedback">{{ TX_INVALID_INPUT }}</div>
    </div>
    <div class="col-md-8">
    </div>

    <div class="col-md-4">
        <label for="password" class="form-label">{{ TX_PASSWORD }}</label>
        <input type="password" class="form-control" id="password" name="password" aria-describedby="passwordHelpBlock" required>
        <div id="passwordHelpBlock" class="form-text">{{ TX_HELP_PASSWORD }}</div>
        <div class="invalid-feedback">{{ TX_INVALID_INPUT }}</div>
    </div>
    <div class="col-md-8">
    </div>

    <div class="col-12 py-2" id="alertPlace"></div>
    <div class="col-12 text-center">
        <button type="submit" id="bSave" class="btn btn-primary w-50" >{{ TX_ENTER }}</button>
    </div>
</form>
JS
function is_valid()
{
    if (!mainform.checkValidity())
    {
        // "custom Bootstrap form validation" (перевірка за шаблонами)
        event.preventDefault();
        event.stopPropagation();
        // для того, щоб показати які поля не пройшли провірку:
        mainform.classList.add('was-validated');
    }
    else
    {
        // якщо пройшло, щоб не залишалися "зелені" поля з галочками
        mainform.classList.remove('was-validated');
    }
}

Перевірити поля по шаблонам (потім виконати AJAX-запит) і залишитися на цій сторінці:

В цьому прикладі, крім bootstrap-перевірки полів за шаблонами mainform.checkValidity(), ще відбувається перевірка за значеннями: check_param(), потім вже виконується AJAX-запит save_param().

<form id="mainform" class="row g-3 needs-validation" novalidate onsubmit="return false;">

    <div class="col-md-4">
        <label for="tTemp" class="form-label">{{ TX_TEMPERATURE }}, °С</label>
        <input type="text" class="form-control" id="tTemp" name="t_temp" value="{{ TEMPERATURE }}" aria-describedby="tempHelpBlock" autocomplete="off" pattern="^-*\d{1,2}(?:[\.,]\d{0,2})?$">
        <div id="tempHelpBlock" class="form-text">{{ TX_AVERAGE_VALUE }}: <b id="avTemp">{% if AV_TEMP %}{{ AV_TEMP }}{% endif %}</b> °С</div>
        <div class="invalid-feedback">{{ TX_INCORRECT_VALUE }} (-25°С ... 45°С)</div>
    </div>
    <div class="col-md-4">
        <label for="nHumd" class="form-label text-end">{{ TX_HUMIDITY }}, %</label>
        <input type="number" class="form-control" id="nHumd" name="n_humd" value="{{ HUMIDITY }}" aria-describedby="humdHelpBlock" min="10" max="90" step="1">
        <div id="humdHelpBlock" class="form-text">{{ TX_AVERAGE_VALUE }}: <b id="avHumd">{% if AV_HUMD %}{{ AV_HUMD }}{% endif %}</b> %</div>
        <div class="invalid-feedback">{{ TX_INCORRECT_VALUE }} (10% ... 90%)</div>
    </div>
    <div class="col-md-4">
        <label for="tPres" class="form-label text-end">{{ TX_PRESSURE }}, гПа</label>
        <input type="text" class="form-control" id="tPres" value="{{ PRESSURE }}" name="t_pres" aria-describedby="presHelpBlock" autocomplete="off" pattern="^\d{3,4}(?:[\.,]\d{0,2})?$">
        <div id="presHelpBlock" class="form-text">{{ TX_AVERAGE_VALUE }}: <b id="avPres">{% if AV_PRES %}{{ AV_PRES }}{% endif %}</b> гПа</div>
        <div class="invalid-feedback">{{ TX_INCORRECT_VALUE }} (950 - 1050 гПа)</div>
    </div>

    <button type="submit" id="bSave" class="btn btn-primary w-50">{{ TX_SAVE }}</button>
</form>
// --------------------------------------------------------------
mainform.addEventListener('submit', event =>
{
    if (!mainform.checkValidity())
    {
        // спочатку "custom Bootstrap form validation" (перевірка за шаблонами)
        event.preventDefault();
        event.stopPropagation();
        // для того, щоб показати які поля не пройшли провірку
        mainform.classList.add('was-validated');
    }
    else
    {
        // потім - перевірка за значеннями, вимикаємо дію псевдо-класів :invalid та :valid
        mainform.classList.remove('was-validated');
        // і будемо використовувати класи .is-valid та .is-invalid для
        // позначення полів, що не пройшли перевірку
        // https://getbootstrap.com/docs/5.2/forms/validation/
        if (check_param())
        {
            bSave.disabled = true;
            save_param();
        }
        else
        {
            return false;
        }
    }
}, false)


/* --------------------------------------------------------------------- */
function check_param()
{
    if ((tTemp.value + nHumd.value + tPres.value).trim() == '')
    {
        if (!confirm(TX_EMPTY_CONFIRM))
        {
            get_param();
            bSave.disabled = false;
            return false;
        }
    }
    else
    {
        let err = 0;

        if (tTemp.value.trim() != '' && (tTemp.value * 1 < -25 || tTemp.value * 1 > 45))
        {
            valid(tTemp, false);
            err = 1;
        } else {
            valid(tTemp, true);
        }

        if (nHumd.value.trim() != '' && (nHumd.value * 1 < 10 || nHumd.value * 1 > 90))
        {
            valid(nHumd, false);
            err = 1;
        } else {
            valid(nHumd, true);
        }

        if (tPres.value.trim() != '' && (tPres.value * 1 < 950 || tPres.value * 1 > 1050))
        {
            valid(tPres, false);
            err = 1;
        } else {
            valid(tPres, true);
        }

        if (err == 1) return false;
    }
    return true;
}

/* --------------------------------------------------------------------- */
function valid(elem, bl)
{
    if (bl == true)  // set valid
    {
        elem.classList.remove('is-invalid');
        elem.classList.add('is-valid');
    }
    else if (bl == false)  // set invalid
    {
        elem.classList.remove('is-valid');
        elem.classList.add('is-invalid');
    }
    else  // clear all
    {
        elem.classList.remove('is-valid');
        elem.classList.remove('is-invalid');
    }
}

/* --------------------------------------------------------------------- */
function input_disabled(bool)
{
    tTemp.disabled = bool;
    nHumd.disabled = bool;
    tPres.disabled = bool;
    bSave.disabled = bool;
}

/* --------------------------------------------------------------------- */
function save_param_success(resp) {

    const json_obj = resp;
    if (resp && 'res' in resp)
    {
        if (resp.res === 'err')  // error
        {
            errmess = ERROR;
            num_errors = resp.err.length;
            for (let i = 1; i <= num_errors; i++)
            {
                errmess += '<br>' + i +'. '+ resp.err[i-1]
            }
            valid(tTemp);
            valid(nHumd);
            valid(tPres);
            alert('danger', errmess);
        }
        else if (resp.res === 'sux')
        {
            alert('hide');
            // message('sux', resp.sux); // not winXP!
            alert('success', resp.sux);
        }
    }
    else
        alert('danger', SRV_UNKNOWN_RESPONSE);
}

/* --------------------------------------------------------------------- */
function save_param_error(err) {
    console.dir(err);
    alert('danger', SRV_ERR);
}

/* --------------------------------------------------------------------- */
function save_param() {

    let fdata = new FormData(document.forms.mainform);

    fetch("/atmo/save/", { method: "POST", body: fdata })

    .then(resp => {
        if (resp.status != 200) {
            alert('danger', SRV_REFUSED_REQUEST +` Status: ${resp.status}`);
        }
        return resp.json();  // return server response as json
    })
    .then(resp => save_param_success(resp))
    .catch(err => save_param_error(err));
    // return false;  // prevent form submit
}

Last updated