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

<Cthuvien:ma ktra> / <Cthuvien:DR_lke> - <BSSLke>

Mô tả​

BSSLke là component React tra cứu dạng ComboBox/AutoComplete, thay thế cho:

  • Chức năng ktra (tra cứu gợi ý khi gõ) của control cũ <Cthuvien:ma>.
  • Control <Cthuvien:DR_lke> (ComboBox tra cứu động từ CSDL qua ham_list, hỗ trợ popup form tham khảo f_tkhao).
  • Chức năng tra cứu của <Cthuvien:nhom>.

Đây là component phức tạp nhất trong bộ BSS Controls. Điểm nổi bật:

  • Tra cứu API tự động (AutoComplete): Khi người dùng gõ ký tự vào ô, component tự động gọi API (thông qua ktra hoặc lke) để lấy danh sách gợi ý từ cơ sở dữ liệu, hiển thị kết quả trong popup bảng dữ liệu.
  • Danh sách tĩnh (Local Options): Hỗ trợ truyền mảng options cố định thay vì gọi API, phù hợp cho các danh sách ngắn không cần tra cứu DB.
  • Phân trang trong Popup: Khi có nhiều kết quả, popup tự chia trang (số dòng mỗi trang lấy từ suggestionLimit trong useAppStore). Hỗ trợ thanh kéo slider kéo trang bằng chuột hoặc phím tắt ← →.
  • Hiển thị Mã hoặc Tên: Thuộc tính hienMaTen quyết định ô input sẽ hiển thị mã hay tên của bản ghi đã chọn. Dù hiển thị cách nào, giá trị gửi ra onChange luôn là mã.
  • Chống giật Grid (Local State): Giá trị gõ vào chỉ cập nhật giao diện nội bộ. Khi onBlur, Tab, hoặc Enter, component mới commit giá trị ra ngoài.
  • Auto-resolve tên: Khi nhận value là mã từ props (VD: "NV001"), component tự động gọi API để tra ngược lấy tên tương ứng hiển thị trên ô (VD: "Nguyễn Văn A").

Thuộc tính​

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

Bảng dưới đây tổng hợp các thuộc tính từ cả <Cthuvien:ma> (phần ktra) và <Cthuvien:DR_lke>:

Control Cũ<BSSLke>KiểuMô tả / Chú ý khi chuyển đổi
tenlabelstringNhãn hiển thị (tự động dịch đa ngôn ngữ).
ktra / ham_listktrastring / functionCũ: Chuỗi ktra="bảng,mã,tên". Mới: Giữ nguyên chuỗi hoặc truyền hàm SuggestFetcher tùy chỉnh.
tctcstringTính chất tra cứu ('A' = Tất cả, mặc định).
nhapreadOnlyboolCũ: nhap="K". Mới: readOnly={true}.
f_tkhao(Không còn)Cũ: Mở form popup riêng bằng F1. Mới: Popup suggest tích hợp sẵn trong component, không cần mở form khác.
traKieuhienMaTenboolCũ (DR_lke): traKieu="T" trả mã|tên. Mới: hienMaTen={true} hiển thị mã, false hiển thị tên. Giá trị gửi ra onChange luôn là mã.
traAn(Tự động)Cũ: Giá trị ẩn lưu mã. Mới: Component tự quản lý mã nội bộ (selectedSuggestMa), không cần khai báo.
gtriDauvalue (khởi tạo)anyCũ (DR_lke): gtriDau="P01{Phòng Kỹ thuật". Mới: Truyền value="P01|Phòng Kỹ thuật" (pipe phân cách), component tự tách và hiển thị.
xep(Không còn)Việc sắp xếp kết quả giờ được xử lý bởi API server hoặc trong hàm SuggestFetcher tùy chỉnh.
luu(Không còn)Lưu vết truy vấn bàn phím không áp dụng trong kiến trúc React mới.
rong / rongB(Tự động)Popup tự động tính toán chiều rộng dựa trên vị trí ô input và viewport.
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 <BSSLke>​

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 ô nhập (tự động dịch đa ngôn ngữ).
labelWidthnumber / stringvar(--bss-label-width)100, '120px'Độ rộng của nhãn label.
ktrastring / function'bảng,mã,tên'Cấu hình tra cứu. Chuỗi: tên bảng, trường mã, trường tên (phẩy phân cách). Function: hàm SuggestFetcher tùy chỉnh gọi API riêng.
lkestring / functionTương tự ktra, dùng khi muốn đặt tên khác. ktra ưu tiên nếu cả hai cùng truyền.
optionsArray[][{ value, label }]Danh sách tĩnh (local) thay vì gọi API. Hỗ trợ key: value/ma/MA và label/ten/TEN.
tcstring'A''C', 'T', 'A'Tính chất danh sách tra cứu truyền vào API.
valueanystring, 'mã|tên'Giá trị binding. Nếu truyền dạng 'mã|tên' (pipe phân cách), component tự tách hiển thị và commit chỉ phần mã.
hienMaTenboolfalsetrue / falsetrue: Ô input hiển thị mã. false (mặc định): Ô input hiển thị tên/label, tooltip hiện mã khi hover.
requiredboolfalsetrue / falseĐánh dấu bắt buộc nhập (hiện sao đỏ).
maxLengthnumberGiới hạn ký tự nhập. Hiển thị bộ đếm lùi ở góc khi hover.
errorstringNội dung lỗi (hoặc tự lấy từ context useValidation).
classNamestring''Class CSS bổ sung cho wrapper.
onChangefunction(e) => voidSự kiện chính. Trả ra { target: { name, value } } — value luôn là mã (không phải tên).
onSuggestSelectfunction({ name, value, row }) => voidSự kiện khi chọn dòng từ popup. Trả về toàn bộ dòng dữ liệu (row) để xử lý thêm (VD: fill tên vào ô khác).

Hoạt động phía Client​

Luồng tra cứu​

  1. Người dùng gõ ký tự vào ô → Component cập nhật displayValue (local state) và gọi API/filter danh sách tĩnh.
  2. Popup hiện ra hiển thị bảng dữ liệu. Nếu kết quả chỉ có đúng 1 dòng khớp hoàn toàn với từ khóa (so sánh mã hoặc tên, case-insensitive), component tự động chọn dòng đó mà không cần người dùng click.
  3. Người dùng click vào dòng hoặc dùng phím ↓/↑ rồi bấm Enter → Component commit mã của dòng đó qua onChange và gọi onSuggestSelect trả về toàn bộ row data.

Auto-resolve tên​

Khi value thay đổi từ bên ngoài (VD: load dữ liệu từ DB), nếu hienMaTen=false, component cần hiển thị tên thay vì mã. Nó sẽ tự gọi API tra cứu ngược (resolveRemoteDisplayText) để tìm dòng tương ứng và gán tên vào ô hiển thị.

Phím tắt​

PhímChức năng
↓Mở popup (nếu chưa mở) / Di chuyển xuống dòng dưới
↑Di chuyển lên dòng trên
←Chuyển về trang trước (khi popup đang mở)
→Chuyển sang trang sau (khi popup đang mở)
EnterChọn dòng đang active / Commit giá trị và nhảy ô
SpaceMở popup và tìm kiếm với giá trị hiện tại
EscĐóng popup
TabCommit giá trị và nhảy ô (mặc định browser)

Thanh kéo trang (Slider)​

Khi có nhiều trang, popup hiện thanh slider ở footer. Người dùng có thể:

  • Click vào vị trí trên track → Nhảy đến trang tương ứng.
  • Kéo (drag) thumb → Preview số trang (tooltip hiện số) và nhả chuột sẽ load trang đó.
  • Hover lên track → Hiện tooltip page number.

Ví dụ​

1. Tra cứu nhân viên (gọi API, hiển thị tên):

<BSSLke
label="Nhân viên"
name="ma_nv"
labelWidth={120}
required={true}
ktra="ns_nhanvien,ma,ten" // Bảng ns_nhanvien, cột mã, cột tên
value={data.ma_nv} // Lưu mã "NV001", hiển thị "Nguyễn Văn A"
onChange={handleChange}
onSuggestSelect={({ row }) => {
// row chứa toàn bộ dòng data từ API
setValue(prev => ({ ...prev, ten_nv: row.ten }));
}}
/>

2. Tra cứu hiển thị mã (thay vì tên):

<BSSLke
label="Tài khoản"
name="ma_tk"
ktra="kt_taikhoan,ma,ten"
hienMaTen={true} // Ô input hiện mã "1111", tooltip hiện "Tiền mặt"
value={data.ma_tk}
onChange={handleChange}
/>

3. Danh sách tĩnh (không gọi API):

<BSSLke
label="Loại hợp đồng"
name="loai_hd"
options={[
{ value: 'LD', label: 'Lao động' },
{ value: 'TV', label: 'Tư vấn' },
{ value: 'TT', label: 'Thời vụ' }
]}
value={data.loai_hd}
onChange={handleChange}
/>

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

<BSSLke
ktra="dm_donvi,ma,ten"
value={row.ma_dv}
onChange={(e) => updateRowField(row.id, 'ma_dv', e.target.value)}
onSuggestSelect={({ row: r }) => updateRowField(row.id, 'ten_dv', r.ten)}
className="w-full"
/>