Chuyển tới nội dung chính

<Cthuvien:nhom> - <BSSList>

Mô tả​

BSSList là component React thay thế cho <Cthuvien:nhom> cũ. Nó hiển thị danh sách chọn dạng dropdown (<select>) cho phép người dùng chọn nhanh một giá trị từ mảng cấu hình lke.

Điểm nổi bật của BSSList:

  • Chống giật Grid (Local State): Giá trị đang chọn được lưu nội bộ. Chỉ khi onBlur, Tab, hoặc Enter, component mới bắn giá trị ra ngoài (onChange), tránh render lại toàn bộ form/grid khi người dùng đang lướt qua các option.
  • Dữ liệu linh hoạt: Mảng lke hỗ trợ nhiều cấu trúc tên trường (value/ma/MA cho giá trị, label/ten/TEN/name/NAME cho hiển thị), giúp tương thích với dữ liệu từ nhiều nguồn API khác nhau mà không cần mapping thủ công.
  • Dòng trống (dongChon): Hỗ trợ thêm option rỗng đầu danh sách cho phép bỏ chọn, thay vì bắt buộc lúc nào cũng phải có giá trị mặc định.
  • Phím tắt: Space mở popup dropdown (native), Enter nhảy sang ô tiếp theo trong form #dt_ct.

Thuộc tính​

So sánh thuộc tính cũ và mới​

<Cthuvien:nhom><BSSList>KiểuMô tả / Chú ý khi chuyển đổi
tenlabelstringTên nhãn hiển thị bên trái (tự động dịch đa ngôn ngữ).
nhapdisabledboolCũ: nhap="K". Mới: Dùng thuộc tính HTML chuẩn disabled={true}.
lke (chuỗi)lke (mảng)ArrayCũ: Chuỗi lke="Xem,Sửa,Xóa" phẩy phân cách. Mới: Mảng Object [{ value: 'V', label: 'Xem' }].
tra (chuỗi)(gộp vào lke)Cũ: Chuỗi tra="V,E,D" phẩy phân cách. Mới: Gộp chung vào trường value của mỗi phần tử trong mảng lke.
cthich(Không còn)Chú thích giờ được xử lý riêng ở lớp logic ngoài component.
kieu_chu(Không còn)Tự viết hoa không áp dụng cho dropdown chọn giá trị.
kt_xoa(Không còn)Logic xóa quản lý ở lớp dữ liệu store/form.

Các thuộc tính của <BSSList>​

TênKiểuMặc địnhCó thể cóMục đích
idstringuseId()Định danh của control. Render ra HTML với prefix BSS_.
namestringsinh tự độngTên trường dữ liệu dùng làm key trong form và validation.
labelstringNhãn hiển thị bên trái dropdown (tự động dịch đa ngôn ngữ).
labelWidthnumber / stringvar(--bss-label-width)100, '120px'Độ rộng của nhãn label.
lkeArray[][{ value, label }]Danh sách option. Mỗi item hỗ trợ nhiều kiểu key: value/ma/MA (giá trị lưu) và label/ten/TEN/name/NAME (hiển thị).
valueanyGiá trị binding hiện tại (phải khớp với value của một phần tử trong mảng lke).
gtriDaustring''Giá trị mặc định ban đầu nếu value là undefined.
dongChonboolfalsetrue / falseNếu true, thêm một dòng <option> rỗng ở đầu danh sách cho phép người dùng bỏ chọn.
requiredboolfalsetrue / falseĐánh dấu bắt buộc chọn (hiện sao đỏ).
errorstringNội dung lỗi (hoặc tự lấy từ context useValidation). Làm viền chuyển đỏ.
isInGridboolfalsetrue / falseĐánh dấu control đang nằm trong lưới GridX (điều chỉnh background khi focus).
classNamestring''Class CSS bổ sung cho wrapper.
onChangefunction(e) => voidSự kiện chính. Trả ra event giả { target: { name, value } } khi commit giá trị.
onChangeValuefunction(val) => voidSự kiện phụ, nhận trực tiếp giá trị string đã chọn (tiện dùng, không cần e.target.value).

Hoạt động phía Client​

  • Chọn giá trị: Khi người dùng chọn option trong dropdown, giá trị chỉ cập nhật local state. Lúc người dùng rời khỏi ô (blur) hoặc bấm Tab/Enter, component mới so sánh giá trị local với giá trị props gốc — nếu khác nhau thì gọi onChange và onChangeValue.
  • Phím Space: Khi đang focus vào dropdown, bấm phím Space sẽ gọi showPicker() (native API) để mở danh sách dropdown của trình duyệt.
  • Phím Enter: Khi focus vào dropdown, nhấn Enter sẽ commit giá trị và tự động nhảy focus sang control kế tiếp (nếu trong form #dt_ct).
  • Dark Mode: Component tự phát hiện chế độ tối/sáng qua useAppStore.isDarkMode để điều chỉnh màu chữ tương ứng.

Ví dụ​

1. Dropdown cơ bản (Chọn chi nhánh):

<BSSList
label="Chi nhánh"
name="chi_nhanh"
labelWidth={120}
required={true}
lke={[
{ value: 'HN', label: 'Hà Nội' },
{ value: 'HCM', label: 'Hồ Chí Minh' },
{ value: 'DN', label: 'Đà Nẵng' }
]}
value={data.chi_nhanh}
onChange={handleChange}
/>

2. Dropdown có dòng trống cho phép bỏ chọn:

<BSSList
label="Phòng ban"
name="phong_ban"
dongChon={true} // Thêm dòng trống đầu tiên
lke={danhSachPhongBan}
value={data.phong_ban}
onChange={handleChange}
onChangeValue={(val) => console.log('Đã chọn:', val)}
/>

3. Sử dụng trong lưới GridX (Không có label):

<BSSList
isInGrid={true}
dongChon={true}
lke={danhSachLoai}
value={row.loai}
onChange={(e) => updateRowField(row.id, 'loai', e.target.value)}
className="w-full"
/>