Schema: فرم از روی JSON
فرم را یکبار با JSON توصیف کنید؛ هم فرم کامل ساخته میشود و هم یک تابع validate() دارید که در مرورگر و در سرور Node با همان قوانین کار میکند. نوعها خودکار به ماژولهای Enhanced Form، Date Picker، Combobox، Upload و Safe Action وصل میشوند. ماژول schema لازم است و باید پیش از بقیه ثبت شود.
<div data-schema="#sch-register"></div>
<script type="application/json" id="sch-register">
{
"title": "ثبتنام",
"action": "https://demo.bana.test/api/register",
"format": "json",
"submit": "ثبتنام",
"successMessage": "ثبتنام انجام شد.",
"fields": [
{ "name": "name", "label": "نام کامل", "required": true, "minLength": 3 },
{ "name": "nid", "type": "national-id", "label": "کد ملی", "required": true, "help": "ارقام فارسی هم پذیرفته میشود." },
{ "name": "mobile", "type": "mobile", "label": "موبایل", "required": true },
{ "name": "birth", "type": "date", "label": "تاریخ تولد", "min": "1300/01/01", "max": "1385/12/29" },
{ "name": "city", "type": "select", "combobox": true, "label": "شهر", "options": [
{ "value": "thr", "label": "تهران" }, { "value": "shz", "label": "شیراز" }, { "value": "tbz", "label": "تبریز" }, { "value": "mhd", "label": "مشهد" } ] },
{ "name": "kind", "type": "radio", "label": "نوع حساب", "required": true, "default": "real",
"options": [ { "value": "real", "label": "حقیقی" }, { "value": "legal", "label": "حقوقی" } ] },
{ "name": "company", "label": "نام شرکت", "required": true, "when": { "field": "kind", "equals": "legal" } },
{ "name": "age", "type": "number", "label": "سن", "min": 18, "max": 99, "integer": true },
{ "name": "agree", "type": "checkbox", "label": "قوانین را میپذیرم", "required": true,
"messages": { "required": "برای ادامه باید قوانین را بپذیرید." } }
]
}
</script>
گزینههای «حقوقی» را انتخاب کنید تا فیلد «نام شرکت» ظاهر شود (when). فیلد پنهان غیرفعال میشود، پس نه اعتبارسنجی میشود و نه ارسال. کد ملی، موبایل و تاریخ با قوانین ایرانی بررسی میشوند و ارقام فارسی خودکار به انگلیسی تبدیل میشوند. JSON داخل <script type="application/json"> داده است، نه کد، پس با CSP سختگیر هم کار میکند.
| کلید | کار |
|---|---|
| type | text (پیشفرض)، textarea، email، url، tel، password، number، mobile، national-id، postal-code، date، select، radio، checkbox، file. |
| required, minLength, maxLength, pattern, min, max, integer | قوانین؛ برای pattern با patternMessage پیام اختصاصی بدهید. min/max در date شمسیاند (1405/01/01). |
| options | برای select و radio: آرایهای از رشته یا { value, label, disabled }. با combobox: true جستوجو هم دارد. |
| when | { field, equals | not | in | truthy } یا ترکیب { all: [...] } / { any: [...] }. |
| messages | پیام اختصاصی برای هر قانون (required، min، …) روی فیلد یا کل Schema. |
| action, method, format, submit, successMessage, redirect | سطح فرم؛ با action فرم به Safe Action وصل میشود (safe: false برای ارسال معمولی). |
| file: accept, maxSize, maxFiles, upload | فیلد فایل با Upload امن. |
// Browser or Node: the same rules, the same Persian messages
import { scValidate, scUse } from "@bana-ui/core/schema";
import { parseJalali, formatJalali } from "@bana-ui/core/datepicker";
// On a server, install the exact Jalali date check (the full browser build does this for you)
scUse({ date: (v) => { const j = parseJalali(v); return j ? formatJalali(j, "en") : false; } });
const { valid, errors, values } = scValidate(schema, requestBody);
if (!valid) return res.status(422).json({ errors }); // Safe Action shows these under each field
save(values); // cleaned: Latin digits, ی/ک, booleans, hidden fields omittedSchema توسط توسعهدهنده نوشته میشود.
pattern به RegExp تبدیل میشود؛ هرگز Schema یا الگوی دریافتی از کاربر را اجرا نکنید. نتیجه validate() جایگزین قوانین دیگر سرور (مجوز، یکتایی، …) نیست. بدون ماژول datepicker، تاریخ فقط از نظر قالب بررسی میشود.