<Cthuvien:ngay> / <Cthuvien:thang> - <BSSCalendar>
Mô tả
BSSCalendar là component React thay thế cho các control nhập ngày/tháng cũ (<Cthuvien:ngay>, <Cthuvien:thang>). Nó được sử dụng để nhập và chọn ngày, giờ, tháng, năm một cách chuẩn xác.
Điểm nổi bật của BSSCalendar:
- Đa năng (All-in-one): Gộp chung xử lý nhập
date,datetime,time,month,yearvào cùng một component (thông qua thuộc tínhtype). - Chống giật Grid (Local State): Giá trị gõ vào chỉ nằm ở state nội bộ (local). Nó tự động format (thêm dấu
/,:) và chặn gõ chữ cái. Khi bấmTab,Enter(hoặconBlur), component mới đẩy giá trị đã format chuẩn ra ngoài (onChange) để cập nhật form/grid, giúp UI mượt mà. - Phím tắt điều hướng: Hỗ trợ chuyển focus tự động sang control kế tiếp khi bấm
Enter(nếu nằm trong form có iddt_ct). - Popup Native: Tận dụng Date Picker gốc (native HTML5) của trình duyệt bằng một input ẩn (type
date/time...). Khi click vào icon lịch/đồng hồ, picker sẽ tự mở. - Xử lý linh hoạt Format (kieu_luu): Tự động parse và build kết quả trả ra theo chuỗi string (
"01/01/2023"), số nguyên integer (20230101), hoặcDateobject tùy cấu hình.
Thuộc tính
So sánh thuộc tính cũ và mới
Dưới đây là bảng tham chiếu các thuộc tính từ control cũ chuyển đổi sang <BSSCalendar>:
| Control Cũ | <BSSCalendar> | Kiểu | Mô tả / Chú ý khi chuyển đổi |
|---|---|---|---|
ten | label | string | Tên/Nhãn của vùng nhập (tự động dịch đa ngôn ngữ). |
nhap | readOnly | bool | Cũ: nhap="K" -> Mới: readOnly={true}. |
kieu_luu | kieu_luu | string | Vẫn giữ nguyên ý nghĩa: I (số Integer, mặc định), S (chuỗi String), D (Date Object). |
kt_xoa | (Không còn) | Việc xóa nội dung khi clear form được quản lý bởi form handler (như Formik/React Hook Form hoặc store). |
Các thuộc tính của <BSSCalendar>
| Tên | Kiểu | Mặc định | Có thể có | Mục đích |
|---|---|---|---|---|
id | string | useId() | Định danh của control. Render ra HTML với prefix BSS_. | |
name | string | sinh tự động | Tên của input (name property). Dùng để nhận diện trong event onChange và validation. | |
label | string | Nhãn hiển thị bên trái của ô nhập. Tự động dịch theo ngôn ngữ. | ||
labelWidth | number / string | var(--bss-label-width) | 110, '120px', '30%' | Độ rộng của nhãn. |
value | any | string, number, Date | Giá trị binding từ form state. Tự động parse và hiển thị tùy theo type và kieu_luu. | |
type | string | 'date' | 'date', 'datetime', 'time', 'month', 'year' | Quyết định định dạng hiển thị và xử lý format logic. |
kieu_luu | string | 'I' | 'I', 'S', 'D' | Kiểu lưu trữ kết quả gửi ra onChange. I=Số, S=Chuỗi, D=Object Date. |
required | bool | false | true / false | Đánh dấu bắt buộc nhập (hiển thị dấu sao * đỏ). |
error | string | Hiển thị lỗi tùy chỉnh. Nếu để rỗng, tự lấy lỗi từ context useValidation. | ||
readOnly | bool | false | true / false | Khóa ô nhập liệu, không cho sửa tay cũng như không gọi picker. |
className | string | '' | Class CSS bổ sung cho thẻ bao ngoài. | |
onChange | function | (e) => void | Hàm callback phát ra event chứa { target: { name, value } } khi xác nhận cập nhật. |
Quy tắc định dạng (Format)
Dựa vào type và kieu_luu, giá trị gửi vào (value) và xuất ra (onChange) sẽ được xử lý:
type | Hiển thị lúc nhập tay | Lưu trữ (kieu_luu = 'I') | Lưu trữ (kieu_luu = 'S') | Lưu trữ (kieu_luu = 'D') |
|---|---|---|---|---|
'date' | dd/mm/yyyy | 20240525 (number) | "25/05/2024" (string) | Date object |
'datetime' | dd/mm/yyyy hh:mm | "20240525 10|30" (string) | — | — |
'time' | hh:mm | "10|30" (string) | — | — |
'month' | mm | "12" (string) | — | — |
'year' | yyyy | "2024" (string) | — | — |
Lưu ý: Component tự động ngăn chặn người dùng nhập ký tự không phải số và tự chèn ký tự phân cách /, :, khoảng trắng tùy theo type.
Ví dụ
Nhập ngày (mặc định):
import { BSSCalendar } from '@/components/BSSCalendar';
export default function ExampleForm() {
const handleChange = (e) => {
// Nếu kieu_luu="I", e.target.value sẽ là số (VD: 20240115)
console.log(e.target.name, e.target.value);
};
return (
<BSSCalendar
id="ngay_sinh"
name="ngaySinh"
label="Ngày sinh"
labelWidth={120}
required={true}
type="date"
kieu_luu="I"
value={data.ngaySinh}
onChange={handleChange}
/>
);
}
Nhập ngày giờ (datetime):
<BSSCalendar
label="Thời gian bắt đầu"
name="tg_batdau"
type="datetime"
value={data.tg_batdau}
onChange={handleChange}
/>
Nhập tháng / năm riêng biệt:
<div className="flex gap-4">
<BSSCalendar label="Tháng" name="thang" type="month" value={data.thang} onChange={handleChange} />
<BSSCalendar label="Năm" name="nam" type="year" value={data.nam} onChange={handleChange} />
</div>
Sử dụng trong lưới (không có label):
<BSSCalendar
type="date"
kieu_luu="S"
value={row.ngay_cap}
onChange={(e) => updateRowField(row.id, 'ngay_cap', e.target.value)}
className="w-full"
/>