TableManager Examples

Complete examples of Now.js TableManager with sorting, filtering, pagination, and CRUD operations

Example 1: Basic Table with Sorting and Filtering

ตัวอย่าง table พื้นฐานที่มีการ sort และ filter พร้อม pagination

ID Name Position Department Status

HTML Code:


              <table class="table border fullwidth" data-table="basic-table" data-source="data/example-table-data.json"
              data-page-size="10">
              <thead>
              <tr>
              <th data-field="id" data-sort="id">ID</th>
              <th data-field="name" data-sort="name" data-filter="true" data-type="text">Name</th>
              <th data-field="position" data-format="lookup" data-sort="position"
              data-options='{"1":"Programmer","2":"Systems Analyst","3":"Project Manager","4":"QA
              Tester","5":"UI/UX
              Designer","6":"Sales","7":"Marketer","8":"Accountant","9":"HR Officer"}'>
              Position</th>
              <th data-field="department" data-format="lookup" data-filter="true" data-type="select"
              data-show-all="true" class="center"
              data-options='{"1":"Engineering","2":"Business Analysis","3":"Project
              Management","4":"QA","5":"UI/UX","6":"Sales","7":"Marketing","8":"Accounting","9":"Human
              Resources"}'>
              Department</th>
              <th data-field="status" data-sort="status" data-filter="true" data-type="select" data-format="lookup"
              data-show-all="true" class="center" data-cell-class="right"
              data-options='{"1":"Working","2":"On
              Leave","3":"Resigned","4":"Probation"}'>
              Status</th>
              </tr>
              </thead>
              <tbody></tbody>
              </table>
            
Note:
  • Static HTML: ใช้ class attribute ปกติสำหรับ <th>, ใช้ data-cell-class สำหรับ <td>
  • Dynamic Columns (API): ใช้ class สำหรับ <th>, ใช้ cellClass สำหรับ <td>
  • แยกกันเด็ดขาด ไม่มี fallback ระหว่าง th และ td

Example 2: Checkboxes and Bulk Actions

Table พร้อม checkboxes สำหรับเลือกแถวและทำ bulk actions

Name Email Department Status Salary

HTML Code:

<table data-table="bulk-actions-table"
              data-source="data/example-table-data.json"
              data-show-checkbox="true"
              data-actions='{"delete":"Delete","activate":"Activate"}'
              data-action-url="api/bulk-action"
              data-action-button="Process Selected">
              <!-- table content -->
              </table>

JavaScript:

// Listen to action completion
              document.addEventListener('table:action-complete', (e) => {
              const {tableId, action, items, response} = e.detail;
              console.log(`${action} completed for ${items.length} items`);

              // Reload table data
              TableManager.loadTableData(tableId);
              });

Example 3: Row Actions with Dropdown Menu

Table พร้อม dropdown menu สำหรับ row actions - ใช้ submenu configuration

ID Name Email Position Status

HTML Code:

<table data-table="row-actions-table"
              data-source="data/example-table-data.json"
              data-row-actions='{
              "view": {
              "label": "View",
              "className": "btn btn-info icon-published1"
              },
              "actions": {
              "label": "Actions",
              "className": "btn btn-primary dropdown icon-menu",
              "submenu": {
              "edit": {
              "label": "Edit",
              "className": "icon-edit"
              },
              "delete": {
              "label": "Delete",
              "className": "color-red icon-delete"
              }
              }
              }
              }'>
              <thead>
              <tr>
              <th data-field="name">Name</th>
              <th data-field="email">Email</th>
              </tr>
              </thead>
              <tbody></tbody>
              </table>

Note:

Split Button: ใช้ submenu configuration เพื่อสร้าง split button โดยมีปุ่ม View เป็นปุ่มหลัก และปุ่ม Actions dropdown (hover) ที่มี Edit และ Delete ใน submenu

Example 4: Server-Side Pagination and Filtering

Table ที่โหลดข้อมูลจาก API พร้อม server-side pagination, sorting และ filtering

Note: ตัวอย่างนี้ต้องการ API endpoint ที่รองรับ pagination parameters (page, pageSize, sort, filters)
ID Name Email Phone Status Created Last Visit

HTML Code:

<table data-table="server-side-table"
              data-source="api/v1/users"
              data-page-size="10"
              data-url-params="true">
              <thead>
              <tr>
              <th data-field="name" data-sort="name" data-filter="true">Name</th>
              <th data-field="status" data-filter="true" data-type="select">Status</th>
              </tr>
              </thead>
              </table>

Expected API Response:

{
              "success": true,
              "data": [
              {"id": 1, "name": "John Doe", "email": "john@example.com"},
              {"id": 2, "name": "Jane Smith", "email": "jane@example.com"}
              ],
              "meta": {
              "total": 1000,
              "totalPages": 40,
              "currentPage": 1,
              "pageSize": 10
              },
              "filters": {
              "status": [
              {"value": "1", "text": "Active"},
              {"value": "0", "text": "Inactive"}
              ]
              }
              }

Example 5: Table with Date Formatting

Table ที่แสดงข้อมูลพร้อม date formatting และ number formatting

ID Name Email Position Status Join Date Salary

HTML Code:

<table data-table="inline-edit-table"
              data-source="data/example-table-data.json">
              <thead>
              <tr>
              <th data-field="name" data-sort="name">Name</th>
              <th data-field="joinDate" data-format="date">Join Date</th>
              <th data-field="salary" data-format="number">Salary</th>
              </tr>
              </thead>
              </table>

Available Formats:

// data-format options:
              // - "lookup": แปลงค่าตาม data-options
              // - "date": แสดงวันที่ (YYYY-MM-DD → DD/MM/YYYY)
              // - "datetime": แสดงวันที่และเวลา
              // - "number": แสดงตัวเลขพร้อม comma separator
              // - "currency": แสดงเงิน (ต้องระบุ currency ใน config)

Example 6: Table Footer with Aggregates

Table พร้อม footer ที่แสดงค่ารวม, ค่าเฉลี่ย, และการนับ

ID Name Position Department Salary Join Date

HTML Code:

<table data-table="footer-table"
              data-show-footer="true"
              data-footer-aggregates='{"salary":"sum","id":"count"}'>
              <thead>
              <tr>
              <th data-field="id">ID</th>
              <th data-field="salary" data-format="number">Salary</th>
              </tr>
              </thead>
              <tfoot></tfoot>
              </table>

JavaScript Initialization:

await TableManager.init({
              showFooter: true,
              footerAggregates: {
              salary: 'sum', // แสดงผลรวม
              quantity: 'sum',
              rating: 'avg', // แสดงค่าเฉลี่ย
              id: 'count' // นับจำนวน
              }
              });

Example 7: Client-Side Data Management

Table ที่ใช้ข้อมูลฝั่ง client โดยไม่ต้องเรียก API

ID Product Category Price Stock

JavaScript Code:

// Client-side data
              const products = [
              { id: 1, product: 'Laptop', category: 'Electronics', price: 999, stock: 50 },
              { id: 2, product: 'Mouse', category: 'Accessories', price: 25, stock: 200 },
              { id: 3, product: 'Keyboard', category: 'Accessories', price: 75, stock: 150 }
              ];

              // Set data to table
              TableManager.setData('client-side-table', products);

              // Add new row
              const newProduct = {
              id: products.length + 1,
              product: 'Monitor',
              category: 'Electronics',
              price: 299,
              stock: 75
              };
              products.push(newProduct);
              TableManager.setData('client-side-table', products);

              // Get all data
              const allData = TableManager.getData('client-side-table');

              // Get filtered data
              const filteredData = TableManager.getData('client-side-table', true);

Example 8: Export Data

Export table data เป็น CSV, Excel, หรือ JSON

ID Name Email Department Status Salary

JavaScript Code:

// Export to CSV
              document.getElementById('exportCSV').addEventListener('click', () => {
              TableManager.exportData('export-table', 'csv', {
              filename: 'employees.csv'
              });
              });

              // Export to Excel (server-side)
              document.getElementById('exportExcel').addEventListener('click', () => {
              TableManager.exportData('export-table', 'excel', {
              filename: 'employees.xlsx'
              });
              });

              // Export to JSON
              document.getElementById('exportJSON').addEventListener('click', () => {
              TableManager.exportData('export-table', 'json', {
              filename: 'employees.json'
              });
              });

              // Export filtered data only
              document.getElementById('exportFiltered').addEventListener('click', () => {
              TableManager.exportData('export-table', 'csv', {
              filename: 'filtered_employees.csv',
              filtered: true
              });
              });

Example 9: Filter Actions (Table-level Actions)

ปุ่มและลิงค์ที่ส่ง filter parameters ไปยัง action URL - สำหรับ export, report generation, หรือ bulk operations

Note: เลือก filter ก่อน แล้วกดปุ่ม - filter params จะถูกส่งไปพร้อม request
ID Name Department Status Salary

HTML Code:

<table data-table="filter-actions-table"
              data-source="api/users"
              data-filter-actions='{
              "export": {
              "label": "Export Filtered",
              "url": "api/export",
              "type": "button",
              "className": "btn-primary"
              },
              "report": {
              "label": "View Report",
              "url": "/reports",
              "type": "link",
              "className": "btn-info",
              "target": "_blank"
              }
              }'>
              <!-- table content -->
              </table>

Filter Actions Options:

// data-filter-actions configuration
              {
              "actionKey": {
              "label": "Button Text", // ข้อความบน button/link
              "url": "api/action", // URL สำหรับ action (required)
              "type": "button", // "button" (POST) หรือ "link" (GET redirect)
              "className": "btn-primary icon-xxx", // CSS classes
              "target": "_self", // สำหรับ link: "_blank" เปิด tab ใหม่
              "confirm": "Are you sure?" // ข้อความยืนยัน (optional)
              }
              }

              // Button จะส่ง POST request:
              {
              "action": "export",
              "tableId": "filter-actions-table",
              "filters": {"status": "1", "department": "5"},
              "sort": {"name": "asc"}
              }

              // Link จะ redirect ไปยัง:
              // /reports?status=1&department=5

Event Listener:

// Listen to filter action events
              document.addEventListener('table:filterAction', (e) => {
              const {tableId, action, type, params, response} = e.detail;
              console.log(`Filter action: ${action} (${type})`);
              console.log('Filters:', params);
              });

Example 10: Row Drag & Editable Rows

สาธิตการเปิด/ปิดการลากแถวด้วย drag handle (แสดงเมื่อแก้ไขแถวได้) พร้อม UX ล่าสุด: ghost เป็นไอคอนเล็กติดเคอร์เซอร์, placeholder เส้นประ และล็อกการลากแนวตั้ง

ID Name Department Status Salary

JavaScript Toggle:

const tableId = 'row-sortable-table';

              document.getElementById('enableRowSort').onclick = () => TableManager.enableRowSort(tableId);
              document.getElementById('disableRowSort').onclick = () => TableManager.disableRowSort(tableId);
              document.getElementById('resetRowOrder').onclick = () => TableManager.loadTableData(tableId);

              // Drag handles appear only when allowRowModification is true.
              // Dragging is vertical-only with dashed placeholder and icon ghost at cursor.

Example 11: Cell Elements (ElementManager)

เรนเดอร์ input/select/textarea ในเซลล์ด้วย data-cell-element (หรือ data-type shorthand) พร้อม config ส่งต่อไปยัง ElementManager

Name Email Status

Key Attributes:

  • data-cell-element หรือ data-type (shorthand) เลือกชนิด control
  • data-options สำหรับ select, data-allow-empty เพื่อแสดงตัวเลือกว่าง
  • data-max-length ใช้เมื่อค่ามากกว่า 0 เท่านั้น

Example 12: Dynamic Table Columns

Table headers generated automatically from API column metadata - perfect for multi-language tables or dynamic schemas

Note: ตัวอย่างนี้ใช้ mock API response แบบ static file เพื่อสาธิตการทำงาน

HTML Code:

<table data-table="dynamic-columns-table"
              data-source="api/languages"
              data-dynamic-columns="true">
              <!-- NO thead needed - generated from API -->
              <tbody></tbody>
              </table>

API Response Format:

{
              "columns": [
              {
              "field": "id",
              "label": "ID",
              "sort": "id",
              "type": "number",
              "i18n": true
              },
              {
              "field": "key",
              "label": "Key",
              "sort": "key",
              "searchable": true,
              "i18n": true
              },
              {
              "field": "th",
              "label": "TH",
              "sort": "th",
              "searchable": true,
              "i18n": true
              },
              {
              "field": "en",
              "label": "EN",
              "sort": "en",
              "searchable": true,
              "i18n": true
              }
              ],
              "data": [
              {"id": 1, "key": "Hello", "th": "สวัสดี", "en": "Hello"},
              {"id": 2, "key": "Goodbye", "th": "ลาก่อน", "en": "Goodbye"}
              ]
              }

PHP Example:

// Auto-detect language columns from database
              $columns = [
              ['field' => 'id', 'label' => 'ID', 'sort' => 'id', 'type' => 'number'],
              ['field' => 'key', 'label' => 'Key', 'sort' => 'key', 'searchable' => true]
              ];

              $language = \Kotchasan\DB::create()->first('language');
              foreach ($language as $key => $value) {
              if (!in_array($key, ['id', 'key', 'type', 'js'])) {
              $columns[] = [
              'field' => $key,
              'label' => strtoupper($key),
              'sort' => $key,
              'searchable' => true
              ];
              }
              }

              return ['columns' => $columns, 'data' => $data];

Benefits:

  • Zero HTML Changes: เพิ่ม/ลด คอลัมน์โดยไม่แก้ template
  • Multi-Language Support: เหมาะสำหรับตารางที่มีหลายภาษา
  • Database-Driven: อ่านโครงสร้างจากฐานข้อมูลอัตโนมัติ
  • Full Features: รองรับ sort, filter, search, validation ครบทุกอย่าง

Column Styling with class and cellClass:

แยกการกำหนด CSS class ระหว่าง header และ body cells:

{
              "columns": [
              {
              "field": "id",
              "label": "ID",
              "class": "header-mono", // CSS class for <th> only
              "cellClass": "mono small" // CSS class for <td> only
              },
              {
              "field": "name",
              "label": "Name",
              "class": "header-bold",
              "cellClass": "text-bold"
              },
              {
              "field": "status",
              "label": "Status",
              "cellClass": "badge text-center" // Only td gets class
              }
              ]
              }
Note:
  • class attribute ใช้กับ <th> เท่านั้น
  • cellClass attribute ใช้กับ <td> เท่านั้น
  • ทั้งสองแยกกันเด็ดขาด ไม่มี fallback
  • สามารถกำหนดแค่ตัวใดตัวหนึ่ง หรือทั้งคู่ก็ได้

Use Cases:

  • Language Tables: เพิ่ม/ลด ภาษาได้โดยแค่ ALTER TABLE
  • Custom Fields: Schema ที่ผู้ใช้กำหนดเองได้
  • Multi-Tenant: แต่ละ tenant มี columns ต่างกัน
  • Report Tables: Columns ขึ้นอยู่กับ report type

TableManager Initialization

Global initialization และ configuration สำหรับทุก table

Basic Initialization:

// เริ่มต้น TableManager
              await TableManager.init({
              pageSizes: [10, 25, 50, 100],
              urlParams: true,
              showCheckbox: false,
              confirmDelete: true
              });

Complete Configuration:

await TableManager.init({
              debug: false, // เปิด debug logging
              urlParams: true, // บันทึก state ลง URL
              pageSizes: [10, 25, 50, 100], // ตัวเลือก page sizes
              showCaption: true, // แสดง table caption
              showCheckbox: false, // แสดง checkboxes
              showFooter: false, // แสดง footer
              footerAggregates: {}, // Footer calculations
              searchColumns: [], // Columns สำหรับค้นหา
              persistColumnWidths: true, // บันทึกความกว้าง columns
              allowRowModification: false, // อนุญาต inline editing
              confirmDelete: true, // ยืนยันก่อนลบ
              source: '', // Default data source
              actionUrl: '', // URL สำหรับ bulk actions
              actionButton: 'Process' // Label ของปุ่ม action
              });

Event Handling

TableManager emit events สำหรับ tracking และ custom handling

// Table loaded
              document.addEventListener('table:loaded', (e) => {
              const {tableId, data, meta} = e.detail;
              console.log(`Table ${tableId} loaded with ${data.length} records`);
              });

              // Table sorted
              document.addEventListener('table:sorted', (e) => {
              const {tableId, field, direction} = e.detail;
              console.log(`Sorted by ${field} ${direction}`);
              });

              // Table filtered
              document.addEventListener('table:filtered', (e) => {
              const {tableId, filters} = e.detail;
              console.log('Active filters:', filters);
              });

              // Page changed
              document.addEventListener('table:page-changed', (e) => {
              const {tableId, page, pageSize} = e.detail;
              console.log(`Page changed to ${page}`);
              });

              // Selection changed
              document.addEventListener('table:selection-changed', (e) => {
              const {tableId, selected, count} = e.detail;
              console.log(`${count} rows selected`);
              });

              // Field changed (inline editing)
              document.addEventListener('table:field-changed', (e) => {
              const {tableId, field, value, oldValue, rowData, success} = e.detail;
              if (success) {
              console.log(`${field} updated successfully`);
              }
              });

              // Bulk action complete
              document.addEventListener('table:action-complete', (e) => {
              const {tableId, action, items, response} = e.detail;
              console.log(`${action} completed for ${items.length} items`);
              });