Jquery使用(2):query.validate.js使用实例

本文介绍了一个基于JavaScript和jQuery实现的用户注册验证过程,包括用户名、密码和邮箱的输入验证,确保用户输入的数据符合预设规则。通过使用jQuery Validate插件,实现了表单的实时验证,并提供了错误提示信息,提升用户体验。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

1.效果

2.JS部分

<script type="text/javascript" src="JSStyle/js/jquery-1.2.6.pack.js"></script>
 <script type="text/javascript" src="JSStyle/js/jquery.validate.js"></script>

<script type="text/javascript" language="javascript">
    $(function() {
        $("#Button1").click(function() {
            $("#form1").validate({
                rules:
                    {
                        "userName":
                        {
                            required: true
                        },
                        "pwd":
                        {
                            required: true,
                            number: true
                        },
                        "email":
                        {
                            required: true,
                            email: true
                        }
                    },
                messages:
                    {
                        "userName":
                        {
                            required: "<strong style='color:red'>请输入用户名</strong>"

                        },
                        "pwd":
                        {
                            required: "<strong style='color:red'>请输入密码</strong>",
                            number: "<strong style='color:red'>请输入整数</strong>"
                        },
                        "email":
                        {
                            required: "请输入邮箱",
                            email: "邮箱格式不正确"
                        }
                    },
                onkeyup: false
            });
        });
    });
   
       
    </script>

3.界面

<form id="form2" runat="server">
    <table>
    <tr>
    <td>
    用户名:
    </td>
    <td>
    <input type="text" name="userName" />
    </td>
    </tr>
    <tr>
    <td>
    密码:
    </td>
    <td>
    <input type="text" name="pwd" />
    </td>
  
    <td>
    邮箱:
    </td>
    <td>
    <input type="text" name="email" />
    </td>
    </tr>
    </table>
    &nbsp;
    
    <asp:Button ID="Button1" runat="server" Text="Button" onclick="Button1_Click" />
    </form>

import React, { useState, useEffect, useCallback, useMemo } from "react"; import { JsonForms } from "@jsonforms/react"; import { materialCells, materialRenderers } from &#39;@jsonforms/material-renderers&#39;; import EnumSelectRenderer, { EnumSelectRendererTester } from &#39;../../renderer/EnumSelectRenderer&#39;; import BaseRenderer, { BaseRendererTester } from &#39;../../renderer/BaseRenderer&#39;; import { vanillaCells, vanillaRenderers, vanillaStyles, JsonFormsStyleContext, } from "@jsonforms/vanilla-renderers"; import { useTranslation } from "react-i18next"; import formSchema from "./form-schema.json"; import formUischema from "./form-ui-schema.json"; import liststyle from "../../../style/design-system-form.json"; import &#39;../style/global.css&#39;; import &#39;../style/S-ECSCM.css&#39;; import "tabulator-tables/dist/css/tabulator.min.css"; import { ReactTabulator, ReactTabulatorOptions } from &#39;react-tabulator&#39;; import { useUnifiedForm } from &#39;../../../yupCommon/useUnifiedForm&#39;; import { useYupI18n } from &#39;../../../yupCommon/useYupI18n&#39;; import { createValidationSchema } from &#39;./validationSchemas&#39;; import initdata from &#39;./table-data.json&#39;; const tableData = initdata["table"]; const styleContextValue = { styles: [...vanillaStyles, ...liststyle] }; import { rankWith, scopeEndsWith, and, or, schemaTypeIs } from &#39;@jsonforms/core&#39;; import useProtectedNavigate from "../../../services/useProtectedNavigate"; import * as Yup from "yup"; import $ from &#39;jquery&#39;; import { useHttpClient } from &#39;../../httpClient&#39;; import { useUserData } from &#39;../../../UserContext&#39;; const sampleData = { "number": "111", "parts": "222", "partsid": "", "products": "", "productsid": "", "shop": "", "shopid": "", "status-category": "", "survey-category": ["test1", "test2"], "request-category": "", "request-dept": "", "request-person": "", "requestdate_min": "", "requestdate_max": "", "expected_response_min": "", "expected_response_max": "", "response_date_min": "", "response_date_max": "" }; const SECSCMTEST = () => { const { t: translation, i18n: i18nInstance } = useTranslation(); const locale = i18nInstance.language; const protectedNavigate = useProtectedNavigate(); const [statusSelected, setStatusSelected] = useState(false); const tableRef = React.useRef<{table?: Tabulator;}>(null); const [tableData, setTableData] = useState([]); const [totalRecords, setTotalRecords] = useState(0); const [currentPage, setCurrentPage] = useState(1); const [totalPages, setTotalPages] = useState(0); // 使用多语言 Yup 配置 const { createLabeledSchema, currentLang } = useYupI18n(); // 创建多语言验证 schema const validationSchema = useMemo(() => { const baseSchema = createValidationSchema(currentLang); return createLabeledSchema(baseSchema); }, [createLabeledSchema, currentLang]); // 使用改进后的统一表单管理(现在支持输入法兼容和多语言) const { formData, validationErrors, isValid, isSubmitting, updateFormData, updateField, registerField, getFieldValue, getFieldError, resetForm, submitForm } = useUnifiedForm({ schema: validationSchema, initialData: sampleData, debounceMs: 500, // 设置防抖延迟为500ms onSubmit: (data) => { console.log("表单提交数据:", data); alert("表单校验通过,数据提交成功!"); } }); // 添加画面变更时触发的方法,将错误消息放到 validation input-description 中 const updateValidationMessages = useCallback(() => { const validationElements = document.getElementsByClassName(&#39;validation&#39;); Array.from(validationElements).forEach(element => { element.innerHTML = &#39;&#39;; }); Object.entries(validationErrors).forEach(([field, error]) => { // 修正:使用正确的模板字符串语法和原生 DOM API const controlDiv = document.querySelector(`div[id*="${field}"]`); if (controlDiv) { // 在控制容器中查找验证消息容器 const validationDiv = controlDiv.querySelector(&#39;.validation&#39;); if (validationDiv) { // 更新错误消息内容和样式 validationDiv.textContent = error || &#39;&#39;; const htmlElement = validationDiv as HTMLElement; if (error) { htmlElement.style.color = &#39;#ff4444&#39;; htmlElement.style.fontSize = &#39;12px&#39;; htmlElement.style.marginTop = &#39;4px&#39;; htmlElement.style.fontWeight = &#39;400&#39;; htmlElement.style.display = &#39;block&#39;; } else { htmlElement.style.color = &#39;&#39;; htmlElement.style.fontSize = &#39;&#39;; htmlElement.style.marginTop = &#39;&#39;; htmlElement.style.fontWeight = &#39;&#39;; htmlElement.style.display = &#39;none&#39;; } } } }); }, [getFieldError]); const httpClient = useHttpClient(); const getTableData = (page) => { var obj: any = {}; const numbers = $("select[id^=&#39;#/properties/number&#39;]"); if(numbers.length != 0){ obj[&#39;number&#39;] = $("select[id^=&#39;#/properties/number&#39;]")[0].value; }else{ obj[&#39;number&#39;] = null; } obj[&#39;page&#39;] = page; obj[&#39;size&#39;] = 10; httpClient.post(&#39;/SECSCMTEST/getTableData&#39;, obj) .then(response => { console.log(&#39;success:&#39;, response.data); setTableData(response.data.table || []); setTotalRecords(response.data.total || 0); // 保存总记录数 setCurrentPage(page); // 在获取数据后更新最大页数 if (tableRef.current) { const maxPage = Math.ceil((response.data.total || 0) / 10); try { // 尝试不同的方法设置最大页数 if (tableRef.current.setMaxPage) { tableRef.current.setMaxPage(maxPage); } else if (tableRef.current.modules && tableRef.current.modules.page) { tableRef.current.modules.page.setMaxPage(maxPage); } console.log(&#39;设置最大页数成功:&#39;, maxPage); } catch (error) { console.error(&#39;设置最大页数失败:&#39;, error); } } }) .catch(error => { console.error(&#39;Save failed:&#39;, error); }); }; const { userData } = useUserData(); useEffect(() => { if(userData && userData.role){ getTableData(1); } }, []); // 监听 validationErrors 变化,自动更新错误消息显示 useEffect(() => { // 使用 setTimeout 确保 DOM 已经渲染完成 const timer = setTimeout(() => { updateValidationMessages(); }, 100); return () => clearTimeout(timer); }, [validationErrors, updateValidationMessages]); useEffect(() => { if (tableRef.current && tableRef.current.table) { const tabulator = tableRef.current.table; setTimeout(() => { try { tabulator.setColumns(statusSelected ? Columns1 : Columns2); } catch (error) { console.error("Failed to refresh table:", error); } }, 100); } }, [statusSelected]); const cellClickFunc = (_e: any, cell: any) => { const _rowdata = cell.getRow().getData(); const _investigation_no = _rowdata.investigation_no; const _investigation_status = _rowdata.investigation_status; const _representative_supplier_name = _rowdata.representative_supplier_name; if (_investigation_no && _investigation_status && _representative_supplier_name) { protectedNavigate(`/SECSCM005?no=${_investigation_no}&status=${_investigation_status}&date=${_representative_supplier_name}`) } else { console.error("Row data is missing required fields for navigation:", _rowdata); } } const baseColumnConfig = { headerHozAlign: &#39;center&#39; as const, hozAlign: &#39;left&#39; as const, vertAlign: &#39;center&#39; as const, cellClick: (_e: any, cell: any) => { cellClickFunc(_e, cell) } }; const Columns1 = [ { title: &#39;ID&#39;, formatter: "rownum", hozAlign: "center" as const, headerHozAlign: "center" as const, width: 40, headerSort: false }, { title: "", formatter: "rowSelection", titleFormatter: "rowSelection", hozAlign: "center" as const, headerHozAlign: "center" as const, headerSort: false, width: 40 }, { ...baseColumnConfig, title: &#39;調査依頼ID&#39;, field: &#39;investigation_no&#39;}, { ...baseColumnConfig, title: &#39;調査対象&#39;, field: &#39;representative_part_name&#39;}, { ...baseColumnConfig, title: &#39;依頼区分&#39;, field: &#39;representative_part_id&#39;}, { ...baseColumnConfig, title: &#39;依頼部門&#39;, field: &#39;purchased_item_name&#39;}, { ...baseColumnConfig, title: &#39;回答希望日&#39;, field: &#39;representative_supplier_name&#39;}, { title: "个人信息", headerHozAlign: &#39;center&#39; as const, columns: [ { ...baseColumnConfig, title: &#39;最短回答予定日&#39;, field: &#39;representative_supplier_id&#39;}, { ...baseColumnConfig, title: &#39;最長回答予定日&#39;, field: &#39;investigation_status&#39;}, ] }, { ...baseColumnConfig, title: &#39;依頼担当者&#39;, field: &#39;purchased_item_id&#39;}, ]; const Columns2 = [ { title: "", formatter: "rowSelection", titleFormatter: "rowSelection", hozAlign: "center" as const, headerHozAlign: "center" as const, headerSort: false, width: 40 }, { ...baseColumnConfig, title: &#39;調査依頼ID&#39;, field: &#39;investigation_no&#39;}, { ...baseColumnConfig, title: &#39;調査対象&#39;, field: &#39;representative_part_name&#39;}, { ...baseColumnConfig, title: &#39;依頼区分&#39;, field: &#39;representative_part_id&#39;}, { ...baseColumnConfig, title: &#39;依頼部門&#39;, field: &#39;purchased_item_name&#39;}, { ...baseColumnConfig, title: &#39;回答希望日&#39;, field: &#39;representative_supplier_name&#39;}, { ...baseColumnConfig, title: &#39;最短回答予定日&#39;, field: &#39;representative_supplier_id&#39;}, { ...baseColumnConfig, title: &#39;最長回答予定日&#39;, field: &#39;investigation_status&#39;}, { ...baseColumnConfig, title: &#39;依頼担当者&#39;, field: &#39;purchased_item_id&#39;}, ]; const handleFormChange = useCallback((data: any) => { updateFormData(data); setStatusSelected(data["status-category"] && data["status-category"] !== ""); // 表单数据变化时也更新验证消息 setTimeout(() => { updateValidationMessages(); }, 100); }, [updateFormData, updateValidationMessages]); const handleClearForm = () => { resetForm(); }; const ErrorMessage = ({ fieldName }: { fieldName: keyof typeof sampleData }) => { const error = getFieldError(fieldName); return error ? <div style={{ color: "red", fontSize: "12px", marginTop: "2px" }}>{error}</div> : null; }; // 远程数据加载函数 const fetchRemoteData = (url, config, params) => { return new Promise((resolve, reject) => { // 模拟 API 参数(实际项目替换为真实 API) const queryParams = new URLSearchParams({ page: params.page, size: params.size, sort: params.sorters.map(s => `${s.field}:${s.dir}`).join(&#39;,&#39;) }); // 实际项目使用 fetch/axios 替换此部分 setTimeout(() => { const mockData = { last_page: 5, data: Array.from({ length: params.size }, (_, i) => ({ representative_part_id: i + (params.page - 1) * params.size, investigation_no: `用户 ${i + 1}`, representative_part_name: `user${i + 1}@example.com`, representative_supplier_name: `职位 ${Math.floor(Math.random() * 10)}` })) }; resolve(mockData); }, 500); }); }; const options: ReactTabulatorOptions = { renderHorizontal: "virtual", layout: "fitDataTable", selectable: true, pagination: "remote", paginationSize: 10, // 远程分页控制属性 page: 1, // 当前页码 paginationSizeSelector: [10, 25, 50, 100], // 可选的每页条数 // 分页回调函数 //pageLoaded: (pageno: number) => { // if (pageno !== currentPage) { // getTableData(pageno); // } //}, ajaxRequestFunc: fetchRemoteData, ajaxResponse: function(url, params, response) { return { data: response.data, last_page: response.last_page }; } }; const renderers = [ ...vanillaRenderers, { tester: BaseRendererTester, renderer: BaseRenderer } //{ tester: EnumSelectRendererTester, renderer: EnumSelectRenderer } ]; // 修改测试函数,尝试多种方法 const checkTableRef = () => { console.log(&#39;手动检查 tableRef:&#39;); console.log(&#39;tableRef.current:&#39;, tableRef.current); if (tableRef.current) { console.log(&#39;找到 Tabulator 实例&#39;); console.log(&#39;可用方法:&#39;, Object.getOwnPropertyNames(tableRef.current.current)); console.log(&#39;modules:&#39;, tableRef.current.modules); const maxPage = Math.ceil(totalRecords / 10); console.log(&#39;计算的最大页数:&#39;, maxPage); // 尝试多种设置方法 try { if (tableRef.current.current.setMaxPage) { tableRef.current.current.setMaxPage(maxPage); console.log(&#39;方法1成功: setMaxPage&#39;); } else if (tableRef.current.modules && tableRef.current.modules.page) { if (tableRef.current.modules.page.setMaxPage) { tableRef.current.modules.page.setMaxPage(maxPage); console.log(&#39;方法2成功: modules.page.setMaxPage&#39;); } } else { // 尝试重新设置选项 const newOptions = { ...options, maxPage }; console.log(&#39;尝试重新设置选项:&#39;, newOptions); } } catch (error) { console.error(&#39;所有方法都失败:&#39;, error); } } }; return ( <div id="content"> <br /> <details className="details"> <summary className="details-summary">{translation(&#39;common.button.show-select-menu.label&#39;,&#39;no label&#39;)}</summary> <form onSubmit={submitForm}> {/* JsonForms 部分 */} <div style={{ marginBottom: "20px" }}> <JsonFormsStyleContext.Provider value={styleContextValue}> <JsonForms i18n={{locale: locale, translate: (key: string, defaultMessage?: string) => translation(key, defaultMessage || &#39;&#39;)}} schema={formSchema} uischema={formUischema} data={formData} renderers={renderers} cells={vanillaCells} onChange={({ data }) => handleFormChange(data)} validationMode="NoValidation" /> </JsonFormsStyleContext.Provider> </div> {/* 原生HTML表单部分 - 现在支持输入法兼容 */} <div style={{ border: "1px solid #fff"}}> <div className="control" id="#/properties/tel"> <label htmlFor="tel-input" className="label">电话:</label> <input className="validate valid input text-field" id="tel-input" name="tel" type="text" ref={(ref) => registerField(&#39;tel&#39;, ref)} defaultValue={getFieldValue(&#39;tel&#39;)} /> <ErrorMessage fieldName="tel" /> </div> </div> <div id="button-right"> <input type="button" className="button" style={{ marginRight: "20px" }} value={translation(&#39;common.button.clear.label&#39;,&#39;no label&#39;)} onClick={handleClearForm} /> <input type="submit" className="button" value={translation(&#39;common.button.select.label&#39;,&#39;no label&#39;)} disabled={!isValid || isSubmitting} style={{ opacity: (isValid && !isSubmitting) ? 1 : 0.5 }} /> {/* 添加测试按钮 */} <input type="button" className="button" style={{ marginLeft: "20px", backgroundColor: "#ff6600" }} value="测试tableRef" onClick={checkTableRef} /> </div> </form> </details> <br /> <div> <ReactTabulator onRef={(instance) => { tableRef.current = instance; }} columns={Columns2 as any} data={[]} options={options} /> </div> <div style={{ marginTop: "10px" }}> <input className="button" type="button" style={{ marginRight: "30px" }} value={translation(&#39;common.button.select-all.label&#39;,&#39;no label&#39;)} /> <input type="button" className="button" value={translation(&#39;common.button.CSV-download.label&#39;,&#39;no label&#39;)} /> </div> </div> ); }; export default SECSCMTEST; 找出我这个文件的错误
最新发布
07-10
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值