جدول داده

DataTable کامل‌ترین کامپوننت قالب است: جستجو، فیلتر، مرتب‌سازی، صفحه‌بندی، نمایش/پنهان کردن ستون، انتخاب چندگانه، عملیات گروهی، خروجی CSV/اکسل/چاپ و چهار حالت وضعیت (بارگذاری، خالی، خطا، آماده). همه بدون هیچ وابستگی بیرونی نوشته شده است.

استفاده اعلانی (ساده‌ترین راه)

<div data-datatable
     data-resource="orders"
     data-per-page="10"
     data-selectable="true"
     data-search="true"
     data-filters="status=paid|unpaid|refunded">
  <table class="table table--hover"></table>
</div>

ستون‌ها را هم می‌توانید با data-columns (JSON) یا با &lt;th data-column="…"&gt; تعریف کنید:

<th data-column="number" data-type="primary" data-sub="customer" data-sortable>شماره سفارش</th>
<th data-column="total" data-type="currency" data-align="end" data-sortable>مبلغ</th>
<th data-column="status" data-type="badge">وضعیت</th>

استفاده برنامه‌ای

import { createDataTable } from './js/core/datatable.js';

const table = createDataTable(document.querySelector('[data-datatable]'), {
  resource: 'products',
  perPage: 20,
  sort: 'createdAt',
  order: 'desc',
  filters: { status: 'active' },
  columns: [
    { key: 'name', label: 'نام محصول', type: 'primary', sub: 'sku', avatar: 'image', sortable: true },
    { key: 'price', label: 'قیمت', type: 'currency', align: 'end', sortable: true },
    { key: 'inventory', label: 'موجودی', type: 'number', align: 'end' },
    { key: 'rating', label: 'امتیاز', type: 'rating' },
    { key: 'status', label: 'وضعیت', type: 'badge', labels: { active: 'فعال', draft: 'پیش‌نویس' } },
    { key: 'actions', label: 'عملیات', type: 'actions', href: 'ecommerce/product-details.html?id={id}' },
  ],
});

نوع ستون‌ها

typeخروجی
textمتن ساده (پیش‌فرض)
primaryعنوان پررنگ + زیرعنوان (sub) و آواتار اختیاری
numberعدد با جداکننده هزارگان فارسی
currencyمبلغ با ارز فعال
percentدرصد با علامت
dateتاریخ بر اساس تقویم فعال (شمسی/میلادی)
relative«۲ روز پیش»
badgeنشان وضعیت با نقشه labels
progressنوار پیشرفت با عدد
ratingستاره‌ها
booleanتیک/ضربدر با رنگ
avatarتصویر گرد
chipsفهرست برچسب‌ها
linkلینک روی همان مقدار
actionsلینک به صفحه جزئیات با الگوی {id}

فیلترها

فیلترهای سریع با ساختار field=value|value ساخته می‌شوند و می‌توانند به کلید داده یا مقدار نمایشی اشاره کنند. هر یک از این فیلترها به‌صورت &lt;select&gt; کنار جستجو نمایش داده می‌شود:

<div data-datatable data-resource="tickets"
     data-filters="priority=high|normal|low,statusLabel=باز|در حال بررسی|بسته"></div>

رویدادها

import { bus, EVENTS } from './js/core/bus.js';

bus.on(EVENTS.tableSelection, ({ resource, ids }) => console.log(resource, ids));
bus.on(EVENTS.dataChanged, ({ resource, action }) => console.log(resource, action));

خروجی گرفتن

دکمه‌های [data-export="csv|excel|print"] در نوار ابزار جدول به‌صورت خودکار کار می‌کنند. برای هر بخش دیگری از صفحه، کافی است ظرفی را با data-exportable="#selector" علامت بزنید (یا exportable(root) را صدا بزنید).

وضعیت‌ها

حالتنمایش
بارگذاریاسکلتون سطر به‌جای جدول
خالیپیام «موردی یافت نشد» با دکمه پاک‌کردن فیلترها
خطاپیام خطا با دکمه «تلاش دوباره»
انتخاب فعالنوار عملیات گروهی با شمارش و حذف گروهی

ذخیره ترجیحات کاربر

نام منبع (resource) کلید ذخیره است؛ ستون‌های پنهان، ترتیب مرتب‌سازی و تعداد سطر در localStorage با پیشوند nova:table: نگه‌داری می‌شوند و در بازدید بعدی بازگردانده می‌شوند.

localStorage.removeItem('nova:table:orders'); // بازگشت به حالت پیش‌فرض
نکته: اگر جدول را بعد از رندر صفحه می‌سازید، initDataTables(scope) یا createDataTable(node) را صدا بزنید؛ ساخت دوباره روی همان گره بی‌خطر است (کش داخلی WeakMap)
هشدار: برای ستون‌های تاریخی همیشه type: 'date' یا 'relative' بگذارید تا با تغییر تقویم شمسی/میلادی درست به‌روز شوند

Data tables

DataTable is the template's most complete component: search, filters, sorting, pagination, show/hide columns, multi-select, bulk actions, CSV/Excel/print export and four states (loading, empty, error, ready). All of it is written without any external dependency.

Declarative usage (the simplest way)

<div data-datatable
     data-resource="orders"
     data-per-page="10"
     data-selectable="true"
     data-search="true"
     data-filters="status=paid|unpaid|refunded">
  <table class="table table--hover"></table>
</div>

You can also define columns with data-columns (JSON) or with &lt;th data-column="…"&gt;:

<th data-column="number" data-type="primary" data-sub="customer" data-sortable>Order number</th>
<th data-column="total" data-type="currency" data-align="end" data-sortable>Amount</th>
<th data-column="status" data-type="badge">Status</th>

Programmatic usage

import { createDataTable } from './js/core/datatable.js';

const table = createDataTable(document.querySelector('[data-datatable]'), {
  resource: 'products',
  perPage: 20,
  sort: 'createdAt',
  order: 'desc',
  filters: { status: 'active' },
  columns: [
    { key: 'name', label: 'Product name', type: 'primary', sub: 'sku', avatar: 'image', sortable: true },
    { key: 'price', label: 'Price', type: 'currency', align: 'end', sortable: true },
    { key: 'inventory', label: 'Stock', type: 'number', align: 'end' },
    { key: 'rating', label: 'Rating', type: 'rating' },
    { key: 'status', label: 'Status', type: 'badge', labels: { active: 'Active', draft: 'Draft' } },
    { key: 'actions', label: 'Actions', type: 'actions', href: 'ecommerce/product-details.html?id={id}' },
  ],
});

Column types

typeOutput
textPlain text (default)
primaryBold title + subtitle (sub) and optional avatar
numberNumber with localized thousands separators
currencyAmount in the active currency
percentPercentage with sign
dateDate in the active calendar (Jalali/Gregorian)
relative"2 days ago"
badgeStatus badge using the labels map
progressProgress bar with value
ratingStars
booleanColoured check/cross
avatarRound image
chipsList of tags
linkA link on the value itself
actionsLink to a details page using the {id} pattern

Filters

Quick filters are built with the field=value|value syntax and can refer to a data key or a display value. Each of these filters is shown as a &lt;select&gt; next to the search box:

<div data-datatable data-resource="tickets"
     data-filters="priority=high|normal|low,statusLabel=Open|In review|Closed"></div>

Events

import { bus, EVENTS } from './js/core/bus.js';

bus.on(EVENTS.tableSelection, ({ resource, ids }) => console.log(resource, ids));
bus.on(EVENTS.dataChanged, ({ resource, action }) => console.log(resource, action));

Exporting

The [data-export="csv|excel|print"] buttons in the table toolbar work automatically. For any other part of the page, just mark a container with data-exportable="#selector" (or call exportable(root)).

States

StateDisplay
LoadingRow skeletons instead of the table
EmptyA "No items found" message with a clear-filters button
ErrorAn error message with a "Try again" button
Active selectionBulk action bar with a count and bulk delete

Saving user preferences

The resource name (resource) is the storage key; hidden columns, sort order and row count are kept in localStorage with the nova:table: prefix and restored on the next visit.

localStorage.removeItem('nova:table:orders'); // back to the default state
Tip: if you build a table after the page renders, call initDataTables(scope) or createDataTable(node); building again on the same node is safe (internal WeakMap cache)
Warning: always set type: 'date' or 'relative' for date columns so they update correctly when the Jalali/Gregorian calendar changes

جداول البيانات

DataTable هو أكمل مكوّن في القالب: البحث والفلترة والترتيب وترقيم الصفحات وإظهار/إخفاء الأعمدة والتحديد المتعدد والعمليات الجماعية والتصدير إلى CSV/Excel/الطباعة وأربع حالات (تحميل، فارغ، خطأ، جاهز). وكل ذلك مكتوب دون أي اعتماد خارجي.

الاستخدام التصريحي (أبسط طريقة)

<div data-datatable
     data-resource="orders"
     data-per-page="10"
     data-selectable="true"
     data-search="true"
     data-filters="status=paid|unpaid|refunded">
  <table class="table table--hover"></table>
</div>

يمكنك أيضاً تعريف الأعمدة بـ data-columns (JSON) أو بـ &lt;th data-column="…"&gt;:

<th data-column="number" data-type="primary" data-sub="customer" data-sortable>رقم الطلب</th>
<th data-column="total" data-type="currency" data-align="end" data-sortable>المبلغ</th>
<th data-column="status" data-type="badge">الحالة</th>

الاستخدام البرمجي

import { createDataTable } from './js/core/datatable.js';

const table = createDataTable(document.querySelector('[data-datatable]'), {
  resource: 'products',
  perPage: 20,
  sort: 'createdAt',
  order: 'desc',
  filters: { status: 'active' },
  columns: [
    { key: 'name', label: 'اسم المنتج', type: 'primary', sub: 'sku', avatar: 'image', sortable: true },
    { key: 'price', label: 'السعر', type: 'currency', align: 'end', sortable: true },
    { key: 'inventory', label: 'المخزون', type: 'number', align: 'end' },
    { key: 'rating', label: 'التقييم', type: 'rating' },
    { key: 'status', label: 'الحالة', type: 'badge', labels: { active: 'نشط', draft: 'مسودة' } },
    { key: 'actions', label: 'الإجراءات', type: 'actions', href: 'ecommerce/product-details.html?id={id}' },
  ],
});

أنواع الأعمدة

typeالمخرجات
textنص بسيط (افتراضي)
primaryعنوان عريض + عنوان فرعي (sub) وصورة رمزية اختيارية
numberعدد بفواصل آلاف محلية
currencyمبلغ بالعملة النشطة
percentنسبة مئوية مع الإشارة
dateتاريخ حسب التقويم النشط (هجري شمسي/ميلادي)
relative«قبل يومين»
badgeشارة حالة بخريطة labels
progressشريط تقدّم مع القيمة
ratingنجوم
booleanعلامة صح/خطأ ملوّنة
avatarصورة دائرية
chipsقائمة وسوم
linkرابط على القيمة نفسها
actionsرابط إلى صفحة التفاصيل بنمط {id}

الفلاتر

تُبنى الفلاتر السريعة بالصيغة field=value|value ويمكن أن تشير إلى مفتاح البيانات أو إلى القيمة المعروضة. ويُعرض كل فلتر منها كـ &lt;select&gt; بجانب البحث:

<div data-datatable data-resource="tickets"
     data-filters="priority=high|normal|low,statusLabel=مفتوحة|قيد المراجعة|مغلقة"></div>

الأحداث

import { bus, EVENTS } from './js/core/bus.js';

bus.on(EVENTS.tableSelection, ({ resource, ids }) => console.log(resource, ids));
bus.on(EVENTS.dataChanged, ({ resource, action }) => console.log(resource, action));

التصدير

تعمل أزرار [data-export="csv|excel|print"] في شريط أدوات الجدول تلقائياً. ولأي جزء آخر من الصفحة، يكفي تعليم حاوية بـ data-exportable="#selector" (أو استدعاء exportable(root)).

الحالات

الحالةالعرض
التحميلهياكل صفوف بدلاً من الجدول
فارغرسالة «لم يُعثر على عناصر» مع زر مسح الفلاتر
خطأرسالة خطأ مع زر «إعادة المحاولة»
تحديد نشطشريط العمليات الجماعية مع العدّ والحذف الجماعي

حفظ تفضيلات المستخدم

اسم المورد (resource) هو مفتاح الحفظ؛ تُحفظ الأعمدة المخفية وترتيب الفرز وعدد الصفوف في localStorage بالبادئة nova:table: وتُستعاد في الزيارة التالية.

localStorage.removeItem('nova:table:orders'); // العودة إلى الحالة الافتراضية
ملاحظة: إذا أنشأت الجدول بعد عرض الصفحة، فاستدعِ initDataTables(scope) أو createDataTable(node)؛ وإعادة الإنشاء على العقدة نفسها آمنة (ذاكرة WeakMap داخلية)
تحذير: اضبط دائماً type: 'date' أو 'relative' لأعمدة التاريخ لتتحدّث بشكل صحيح عند تبديل التقويم الهجري الشمسي/الميلادي