真实的国产乱ⅩXXX66竹夫人,五月香六月婷婷激情综合,亚洲日本VA一区二区三区,亚洲精品一区二区三区麻豆

成都創(chuàng)新互聯(lián)網(wǎng)站制作重慶分公司

Dojo表單校驗-創(chuàng)新互聯(lián)

tutorials/1015_form_validation/index.md

成都網(wǎng)站建設(shè)、成都網(wǎng)站制作過程中,需要針對客戶的行業(yè)特點、產(chǎn)品特性、目標受眾和市場情況進行定位分析,以確定網(wǎng)站的風格、色彩、版式、交互等方面的設(shè)計方向。創(chuàng)新互聯(lián)建站還需要根據(jù)客戶的需求進行功能模塊的開發(fā)和設(shè)計,包括內(nèi)容管理、前臺展示、用戶權(quán)限管理、數(shù)據(jù)統(tǒng)計和安全保護等功能。

commit 3e0f3ff1ed392163bc65e9cd015c4705cb9c586e

{% section 'first' %}

表單校驗

Overview

本教程將介紹如何在示例應(yīng)用程序的上下文中處理基本的表單校驗。在 注入狀態(tài) 教程中,我們已經(jīng)介紹了處理表單數(shù)據(jù);我們將在這些概念的基礎(chǔ)上,在現(xiàn)有表單上添加校驗狀態(tài)和錯誤信息。本教程中,我們將構(gòu)建一個支持動態(tài)的客戶端校驗和模擬的服務(wù)器端校驗示例。

前提

你可以打開 codesandbox.io 上的教程 或者 下載 示例項目,然后運行 npm install。

本教程假設(shè)你已經(jīng)學習了 表單部件教程 和 狀態(tài)管理教程。

{% section %}

創(chuàng)建存儲表單錯誤的對象

{% task '在應(yīng)用程序上下文中添加表單錯誤。' %}

現(xiàn)在,錯誤對象應(yīng)該對應(yīng)存在于 WorkerForm.tsApplicationContext.ts 文件中的 WorkerFormData。這種錯誤配置有多種處理方式,一種情況是為單個 input 的多個校驗步驟分別設(shè)置錯誤信息?,F(xiàn)在我們將從最簡單的情況開始,即為每個 input 添加布爾類型的 valid 和 invalid 狀態(tài)。

{% instruction '為 WorkerForm.ts 文件中創(chuàng)建一個 WorkerFormErrors 接口' %}

{% include_codefile 'demo/finished/biz-e-corp/src/widgets/WorkerForm.ts' lines:15-19 %}

export interface WorkerFormErrors {
    firstName?: boolean;
    lastName?: boolean;
    email?: boolean;
}

WorkerFormErrors 中的屬性定義為可選,這樣我們就可以為 form 中的字段創(chuàng)建三種狀態(tài):未校驗的、有效的和無效的。

{% instruction '接下來將 formErrors 方法添加到 ApplicationContext 類中' %}

在練習中,完成以下三步:

  1. 在 ApplicationContext 類中創(chuàng)建一個私有字段 _formErrors
  2. ApplicationContext 中為 _formErrors 創(chuàng)建一個 public 訪問器
  3. 更新 WorkerFormContainer.ts 文件中的 getProperties 函數(shù),支持傳入新的錯誤對象

提示:查看 ApplicationContext 類中已有的 _formData 私有字段是如何使用的??砂凑障嗤牧鞒烫砑?_formErrors 變量。

確保 ApplicationContext.ts 中存在以下代碼:

// modify import to include WorkerFormErrors
import { WorkerFormData, WorkerFormErrors } from './widgets/WorkerForm';

// private field
private _formErrors: WorkerFormErrors = {};

// public getter
get formErrors(): WorkerFormErrors {
    return this._formErrors;
}

WorkerFormContainer.ts 中修改后的 getProperties 函數(shù):

function getProperties(inject: ApplicationContext, properties: any) {
    const {
        formData,
        formErrors,
        formInput: onFormInput,
        submitForm: onFormSave
    } = inject;

    return {
        formData,
        formErrors,
        onFormInput: onFormInput.bind(inject),
        onFormSave: onFormSave.bind(inject)
    };
}

{% instruction '最后,修改 WorkerForm.ts 中的 WorkerFormProperties 來接收應(yīng)用程序上下文傳入的 formErrors 對象:' %}

export interface WorkerFormProperties {
    formData: WorkerFormData;
    formErrors: WorkerFormErrors;
    onFormInput: (data: Partial) => void;
    onFormSave: () => void;
}

{% section %}

為 form 表單輸入框綁定校驗

{% task '在 onInput 中執(zhí)行校驗' %}

現(xiàn)在,我們已經(jīng)可以在應(yīng)用程序狀態(tài)中存儲表單錯誤,并將這些錯誤傳給 form 表單部件。但 form 表單依然缺少真正的用戶輸入校驗;為此,我們需要溫習正則表達式并寫一個基本的校驗函數(shù)。

{% instruction '在 ApplicationContext.ts 中創(chuàng)建一個私有方法 _validateInput' %}

跟已存在的 formInput 函數(shù)相似,應(yīng)該為 _validateInput 傳入 Partial 類型的 WorkerFormData 輸入對象。校驗函數(shù)應(yīng)該返回一個 WorkerFormErrors 對象。示例應(yīng)用程序中只展示了最基本的校驗檢查——示例中郵箱地址的正則表達式模式匹配簡潔但有不夠完備。你可以用更健壯的郵箱測試來代替,或者做其它修改,如檢查第一個名字和最后一個名字的最小字符數(shù)。

{% include_codefile 'demo/finished/biz-e-corp/src/ApplicationContext.ts' lines:32-50 %}

private _validateInput(input: Partial): WorkerFormErrors {
    const errors: WorkerFormErrors = {};

    // validate input
    for (let key in input) {
        switch (key) {
            case 'firstName':
                errors.firstName = !input.firstName;
                break;
            case 'lastName':
                errors.lastName = !input.lastName;
                break;
            case 'email':
                errors.email = !input.email || !input.email.match(/^[a-zA-Z0-9.!#$%&’*+/=?^_`{|}~-]+@[a-zA-Z0-9-]+(?:\.[a-zA-Z0-9-]+)*$/);
        }
    }

    return errors;
}

現(xiàn)在,我們將在每一個 onInput 事件中直接調(diào)用校驗函數(shù)來測試它。將下面一行代碼添加到 ApplicationContext.ts 中的 formInput 中:

this._formErrors = deepAssign({}, this._formErrors, this._validateInput(input));

{% instruction '更新 WorkerForm 的渲染方法來顯示校驗狀態(tài)' %}

至此,WorkerForm 部件的 formErrors 屬性中存著每個 form 字段的校驗狀態(tài),每次調(diào)用 onInput 事件時都會更新校驗狀態(tài)。剩下的就是將 valid/invalid 屬性傳給所有輸入部件。幸運的是,Dojo 的 TextInput 部件包含一個 invalid 屬性,可用于在 DOM 節(jié)點上設(shè)置 aria-invalid 屬性,并切換可視化樣式類。

WorkerForm.ts 中更新后的渲染方法,應(yīng)該是將每個 form 字段部件的上 invalid 屬性與 formErrors 對應(yīng)上。我們也為 form 元素添加了一個 novalidate 屬性來禁用原生瀏覽器校驗。

protected render() {
    const {
        formData: { firstName, lastName, email },
        formErrors
    } = this.properties;

    return v('form', {
        classes: this.theme(css.workerForm),
        novalidate: 'true',
        onsubmit: this._onSubmit
    }, [
        v('fieldset', { classes: this.theme(css.nameField) }, [
            v('legend', { classes: this.theme(css.nameLabel) }, [ 'Name' ]),
           w(TextInput, {
                key: 'firstNameInput',
                label:'First Name',
                labelHidden: true,
                placeholder: 'Given name',
                value: firstName,
                required: true,
                invalid: this.properties.formErrors.firstName,
                onInput: this.onFirstNameInput
            }),
           w(TextInput, {
                key: 'lastNameInput',
                label: 'Last Name',
                labelHidden: true,
                placeholder: 'Surname name',
                value: lastName,
                required: true,
                invalid: this.properties.formErrors.lastName,
                onInput: this.onLastNameInput
            })
        ]),
       w(TextInput, {
            label: 'Email address',
            type: 'email',
            value: email,
            required: true,
            invalid: this.properties.formErrors.email,
            onInput: this.onEmailInput
        }),
       w(Button, {}, [ 'Save' ])
    ]);
}

現(xiàn)在,當你在瀏覽器中查看應(yīng)用程序時,每個表單字段的邊框顏色會隨著你鍵入的內(nèi)容而變化。接下來我們將添加錯誤信息,并更新 onInput ,讓檢驗只在第一次失去焦點(blur)事件后發(fā)生。

{% section %}

擴展 TextInput

{% task '創(chuàng)建一個錯誤消息' %}

簡單的將 form 字段的邊框顏色設(shè)置為紅色或綠色并不能告知用戶更多信息——我們需要為無效狀態(tài)添加一些錯誤消息文本。最基本要求,我們的錯誤文本必須與 form 中的 input 關(guān)聯(lián),可設(shè)置樣式和可訪問。一個包含錯誤信息的 form 表單字段看起來應(yīng)該是這樣的:

v('div', { classes: this.theme(css.inputWrapper) }, [
   w(TextInput, {
        ...
        aria: {
            describedBy: this._errorId
        },
        onInput: this._onInput
    }),
    invalid === true ? v('span', {
        id: this._errorId,
        classes: this.theme(css.error),
        'aria-live': 'polite'
    }, [ 'Please enter valid text for this field' ]) : null
])

通過 aria-describeby 屬性將錯誤消息與文本輸入框關(guān)聯(lián),并使用 aria-live 屬性來確保當它添加到 DOM 或發(fā)生變化后能被讀取到。將輸入框和錯誤信息包裹在一個 <div> 中,則在需要時可相對輸入框來獲取到錯誤信息的位置。

{% instruction '擴展 TextInput,創(chuàng)建一個包含錯誤信息和 onValidate 方法的 ValidatedTextInput 部件' %}

為多個文本輸入框重復(fù)創(chuàng)建相同的錯誤消息樣板明顯是十分啰嗦的,所以我們將擴展 TextInput。這還將讓我們能夠更好的控制何時校驗,例如,也可以添加給 blur 事件?,F(xiàn)在,只是創(chuàng)建一個 ValidatedTextInput 部件,它接收與 TextInput 相同的屬性接口,但多了一個 errorMessage 字符串和 onValidate 方法。它應(yīng)該返回與上面相同的節(jié)點結(jié)構(gòu)。

你也需要創(chuàng)建包含 errorinputWrapper 樣式類的 validatedTextInput.m.css 文件,盡管我們會棄用本教程中添加的特定樣式:

.inputWrapper {}

.error {}
import { WidgetBase } from '@dojo/framework/widget-core/WidgetBase';
import { TypedTargetEvent } from '@dojo/framework/widget-core/interfaces';
import { v, w } from '@dojo/framework/widget-core/d';
import uuid from '@dojo/framework/core/uuid';
import { ThemedMixin, theme } from '@dojo/framework/widget-core/mixins/Themed';
import TextInput, { TextInputProperties } from '@dojo/widgets/text-input';
import * as css from '../styles/validatedTextInput.m.css';

export interface ValidatedTextInputProperties extends TextInputProperties {
    errorMessage?: string;
    onValidate?: (value: string) => void;
}

export const ValidatedTextInputBase = ThemedMixin(WidgetBase);

@theme(css)
export default class ValidatedTextInput extends ValidatedTextInputBase {
    private _errorId = uuid();

    protected render() {
        const {
            disabled,
            label,
            maxLength,
            minLength,
            name,
            placeholder,
            readOnly,
            required,
            type = 'text',
            value,
            invalid,
            errorMessage,
            onBlur,
            onInput
        } = this.properties;

        return v('div', { classes: this.theme(css.inputWrapper) }, [
           w(TextInput, {
                aria: {
                    describedBy: this._errorId
                },
                disabled,
                invalid,
                label,
                maxLength,
                minLength,
                name,
                placeholder,
                readOnly,
                required,
                type,
                value,
                onBlur,
                onInput
            }),
            invalid === true ? v('span', {
                id: this._errorId,
                classes: this.theme(css.error),
                'aria-live': 'polite'
            }, [ errorMessage ]) : null
        ]);
    }
}

你可能已注意到,我們創(chuàng)建的 ValidatedTextInput 包含一個 onValidate 屬性,但我們還沒有用到它。在接下來的幾步中,這將變得非常重要,因為我們可以對何時校驗做更多的控制?,F(xiàn)在,只是把它當做一個占位符。

{% instruction '在 WorkerForm 中使用 ValidatedTextInput' %}

現(xiàn)在 ValidatedTextInput 已存在,讓我們在 WorkerForm 中導(dǎo)入它并替換掉 TextInput,并在其中寫一些錯誤消息文本:

Import 語句塊

{% include_codefile 'demo/finished/biz-e-corp/src/widgets/WorkerForm.ts' lines:1-7 %}

import { WidgetBase } from '@dojo/framework/widget-core/WidgetBase';
import { TypedTargetEvent } from '@dojo/framework/widget-core/interfaces';
import { v, w } from '@dojo/framework/widget-core/d';
import { ThemedMixin, theme } from '@dojo/framework/widget-core/mixins/Themed';
import Button from '@dojo/widgets/button';
import ValidatedTextInput from './ValidatedTextInput';
import * as css from '../styles/workerForm.m.css';

render() 方法內(nèi)部

{% include_codefile 'demo/finished/biz-e-corp/src/widgets/WorkerForm.ts' lines:72-108 %}

v('fieldset', { classes: this.theme(css.nameField) }, [
    v('legend', { classes: this.theme(css.nameLabel) }, [ 'Name' ]),
   w(ValidatedTextInput, {
        key: 'firstNameInput',
        label: 'First Name',
        labelHidden: true,
        placeholder: 'Given name',
        value: firstName,
        required: true,
        onInput: this.onFirstNameInput,
        onValidate: this.onFirstNameValidate,
        invalid: formErrors.firstName,
        errorMessage: 'First name is required'
    }),
   w(ValidatedTextInput, {
        key: 'lastNameInput',
        label: 'Last Name',
        labelHidden: true,
        placeholder: 'Surname name',
        value: lastName,
        required: true,
        onInput: this.onLastNameInput,
        onValidate: this.onLastNameValidate,
        invalid: formErrors.lastName,
        errorMessage: 'Last name is required'
    })
]),
w(ValidatedTextInput, {
    label: 'Email address',
    type: 'email',
    value: email,
    required: true,
    onInput: this.onEmailInput,
    onValidate: this.onEmailValidate,
    invalid: formErrors.email,
    errorMessage: 'Please enter a valid email address'
}),

{% task '創(chuàng)建從 onFormInput 中提取出來的 onFormValidate 方法' %}

{% instruction '傳入 onFormValidate 方法來更新上下文' %}

現(xiàn)在校驗邏輯毫不客氣的躺在 ApplicationContext.ts 中的 formInput 中。現(xiàn)在我們將它抬到自己的 formValidate 函數(shù)中,并參考 onFormInput 模式,將 onFormValidate 傳給 WorkerForm。這里有三個步驟:

  1. ApplicationContext.ts 中添加 formValidate 方法,并將 formInput 中更新 _formErrors 代碼放到 formValidate 中:

    public formValidate(input: Partial): void {
        this._formErrors = deepAssign({}, this._formErrors, this._validateInput(input));
        this._invalidator();
    }
    
    public formInput(input: Partial): void {
        this._formData = deepAssign({}, this._formData, input);
        this._invalidator();
    }
  2. 更新 WorkerFormContainer,將 formValidate 傳給 onFormValidate

    function getProperties(inject: ApplicationContext, properties: any) {
        const {
            formData,
            formErrors,
            formInput: onFormInput,
            formValidate: onFormValidate,
            submitForm: onFormSave
        } = inject;
    
        return {
            formData,
            formErrors,
            onFormInput: onFormInput.bind(inject),
            onFormValidate: onFormValidate.bind(inject),
            onFormSave: onFormSave.bind(inject)
        };
    }
  3. WorkerForm 中先在 WorkerFormProperties 接口中添加 onFormValidate:

    export interface WorkerFormProperties {
        formData: WorkerFormData;
        formErrors: WorkerFormErrors;
        onFormInput: (data: Partial) => void;
        onFormValidate: (data: Partial) => void;
        onFormSave: () => void;
    }

    然后為每個 form 字段的校驗創(chuàng)建內(nèi)部方法,并將這些方法(如 onFirstNameValidate)傳給每個 ValidatedTextInput 部件。這將使用與 onFormInput、onFirstNameInput、onLastNameInputonEmailInput 相同的模式:

    protected onFirstNameValidate(firstName: string) {
        this.properties.onFormValidate({ firstName });
    }
    
    protected onLastNameValidate(lastName: string) {
        this.properties.onFormValidate({ lastName });
    }
    
    protected onEmailValidate(email: string) {
        this.properties.onFormValidate({ email });
    }

{% instruction '在 ValidatedTextInput 中調(diào)用 onValidate' %}

你可能已注意到,當用戶輸入事件發(fā)生后,form 表單不再校驗。這是因為我們已不在 ApplicationContext.tsformInput 中處理校驗,但我們還沒有將校驗添加到其它地方。要做到這一點,我們在 ValidateTextInput 中添加以下私有方法:

private _onInput(value: string) {
    const { onInput, onValidate } = this.properties;
    onInput && onInput(value);
    onValidate && onValidate(value);
}

現(xiàn)在將它傳給 TextInput,替換掉 this.properties.onInput

w(TextInput, {
    aria: {
        describedBy: this._errorId
    },
    disabled,
    invalid,
    label,
    maxLength,
    minLength,
    name,
    placeholder,
    readOnly,
    required,
    type,
    value,
    onBlur,
    onInput: this._onInput
})

表單錯誤功能已恢復(fù),并為無效字段添加了錯誤消息。

{% section %}

使用 blur 事件

{% task '僅在第一次 blur 事件后開始校驗' %}

現(xiàn)在只要用戶開始在字段中輸入就會顯示校驗信息,這是一種不友好的用戶體驗。在用戶開始輸入郵箱地址時就看到 “invalid email address” 是沒有必要的,也容易分散注意力。更好的模式是將校驗推遲到第一次 blur 事件之后,然后在 input 事件中開始更新校驗信息。

{% aside 'Blur 事件' %}
當元素失去焦點后會觸發(fā) blur 事件。
{% endaside %}

現(xiàn)在已在 ValidatedTextInput 部件中調(diào)用了 onValidate,這是可以實現(xiàn)的。

{% instruction '創(chuàng)建一個私有的 _onBlur 函數(shù),它會調(diào)用 onValidate' %}

ValidatedTextInput.ts 文件中:

private _onBlur(value: string) {
    const { onBlur, onValidate } = this.properties;
    onValidate && onValidate(value);
    onBlur && onBlur();
}

我們僅需在第一次 blur 事件之后使用這個函數(shù),因為隨后的校驗交由 onInput 處理。下面的代碼將根據(jù)輸入框之前是否已校驗過,來使用 this._onBlurthis.properties.onBlur

{% include_codefile 'demo/finished/biz-e-corp/src/widgets/ValidatedTextInput.ts' lines:50-67 %}

w(TextInput, {
    aria: {
        describedBy: this._errorId
    },
    disabled,
    invalid,
    label,
    maxLength,
    minLength,
    name,
    placeholder,
    readOnly,
    required,
    type,
    value,
    onBlur: typeof invalid === 'undefined' ? this._onBlur : onBlur,
    onInput: this._onInput
}),

現(xiàn)在只剩下修改 _onInput,如果字段已經(jīng)有一個校驗狀態(tài),則調(diào)用 onValidate:

{% include_codefile 'demo/finished/biz-e-corp/src/widgets/ValidatedTextInput.ts' lines:24-31 %}

private _onInput(value: string) {
    const { invalid, onInput, onValidate } = this.properties;
    onInput && onInput(value);

    if (typeof invalid !== 'undefined') {
        onValidate && onValidate(value);
    }
}

嘗試輸入一個郵箱地址來演示這些變化;它應(yīng)該只在第一次離開 form 字段之后顯示錯誤信息(或綠色邊框),而在接下來的編輯中將立即觸發(fā)校驗。

{% section %}

在提交時校驗

{% task '創(chuàng)建一個模擬的服務(wù)器端校驗,以處理提交的 form 表單' %}

到目前為止,我們的代碼給用戶提供了友好提示,但并不能防止我們將無效數(shù)據(jù)提交到我們的 worker 數(shù)組中。我們需要在 submitForm 操作中添加兩個獨立的檢查:

  1. 如果已存在的校驗函數(shù)捕獲到任何錯誤,則立即提交失敗。
  2. 執(zhí)行額外檢查(本示例中我們將檢查郵箱唯一性)。這是我們在真正的應(yīng)用程序中加入服務(wù)器端校驗的地方。

{% instruction '在 ApplicationContext.ts 中創(chuàng)建一個私有方法 _validateOnSubmit' %}

新增的 _validateOnSubmit 方法應(yīng)該從對所有 _formData 運行已存在的輸入校驗開始,然后在存在任一錯誤后返回 false:

private _validateOnSubmit(): boolean {
    const errors = this._validateInput(this._formData);
    this._formErrors = deepAssign({ firstName: true, lastName: true, email: true }, errors);

    if (this._formErrors.firstName || this._formErrors.lastName || this._formErrors.email) {
        console.error('Form contains errors');
        return false;
    }

    return true;
}

接下來我們添加一個檢查:假設(shè)每個工人的郵箱必須是唯一的,所以我們將在 _workerData 數(shù)組中測試輸入的郵箱地址是否已存在。在現(xiàn)實中安全起見,這個檢查運行在服務(wù)器端:

{% include_codefile 'demo/finished/biz-e-corp/src/ApplicationContext.ts' lines:53-70 %}

private _validateOnSubmit(): boolean {
    const errors = this._validateInput(this._formData);
    this._formErrors = deepAssign({ firstName: true, lastName: true, email: true }, errors);

    if (this._formErrors.firstName || this._formErrors.lastName || this._formErrors.email) {
        console.error('Form contains errors');
        return false;
    }

    for (let worker of this._workerData) {
        if (worker.email === this._formData.email) {
            console.error('Email must be unique');
            return false;
        }
    }

    return true;
}

修改完 ApplicationContext.ts 中的 submitForm 函數(shù)后,只有有效的工人數(shù)據(jù)才能提交成功。我們也需要在成功提交后清空 _formErrors_formData

{% include_codefile 'demo/finished/biz-e-corp/src/ApplicationContext.ts' lines:82-92 %}

public submitForm(): void {
    if (!this._validateOnSubmit()) {
        this._invalidator();
        return;
    }

    this._workerData = [ ...this._workerData, this._formData ];
    this._formData = {};
    this._formErrors = {};
    this._invalidator();
}

{% section %}

總結(jié)

本教程不可能涵蓋所有可能用例,但是存儲、注入和顯示校驗狀態(tài)的基本模式,為創(chuàng)建復(fù)雜的表單校驗提供了堅實的基礎(chǔ)。接下來將包含以下步驟:

  • 為傳遞給 WorkerForm 的對象配置錯誤信息
  • 創(chuàng)建一個 toast 來顯示提交時的錯誤
  • 為一個 form 字段添加多個校驗步驟

你可以在 codesandbox.io 中打開完整示例或下載項目。

{% section 'last' %}

另外有需要云服務(wù)器可以了解下創(chuàng)新互聯(lián)scvps.cn,海內(nèi)外云服務(wù)器15元起步,三天無理由+7*72小時售后在線,公司持有idc許可證,提供“云服務(wù)器、裸金屬服務(wù)器、高防服務(wù)器、香港服務(wù)器、美國服務(wù)器、虛擬主機、免備案服務(wù)器”等云主機租用服務(wù)以及企業(yè)上云的綜合解決方案,具有“安全穩(wěn)定、簡單易用、服務(wù)可用性高、性價比高”等特點與優(yōu)勢,專為企業(yè)上云打造定制,能夠滿足用戶豐富、多元化的應(yīng)用場景需求。


網(wǎng)頁標題:Dojo表單校驗-創(chuàng)新互聯(lián)
網(wǎng)址分享:http://weahome.cn/article/gssep.html

其他資訊

在線咨詢

微信咨詢

電話咨詢

028-86922220(工作日)

18980820575(7×24)

提交需求

返回頂部