SearchEntry
Picker entity với type-ahead search — dùng cho dimension table lớn (Customer, Product…). Bind foreign key (int).
Source:
Core/Components/SearchEntry.csComponentTypetrong DB:DropdownvớiPrecision < 2(alias chính). Cũng dùng đượcSearchEntryqua reflection. ĐặtPrecision >= 2cùngComponentType = Dropdown→ Core pickMultipleSearchEntrythay thế.
Cấu hình
ComType: Dropdown # alias chính (Precision < 2 → SearchEntry)
FieldName: CustomerId
Reference: Customer
DataSourceFilter: ?$filter=Active eq true # bắt buộc đủ "?$filter="
Field DB dùng
| Field | Vai trò |
|---|---|
FieldName | Property entity bind FK (int CustomerId). |
Reference | Type entity tham chiếu (vd Customer). |
RefName | Tên entity tham chiếu dạng string. |
RefClass | Class CSS của hiển thị reference. |
DataSourceFilter | OData filter đủ ?$filter=..., có thể có placeholder {<Field>} cho cascade. |
Template | Template hiển thị suggestion ("{Code} - {Name}"). |
FormatData | Format trong dropdown. |
FormatEntity | Format hiển thị entity đã chọn (sau khi pick). |
Editable | False → render disabled (read-only). |
Events | JSON map event → method C# (Change, AfterCreated, AfterRender). |
HideGrid | True → ẩn nút mở popup picker (kèm phím mũi tên phải). |
LocalData | Inline JSON list data → bypass API call (test / fixed list). |
LocalHeader | Cấu hình cột cho popup picker grid (local). |
LocalRender | True → render custom local thay vì grid mặc định. |
Row | Số dòng hiển thị popup picker (chiều cao). |
Precision | Số chữ số thập phân (rare cho picker). |
PlainText | True → render plain. |
IsPivot | True → render dạng pivot. |
GroupBy | Field group by trong popup picker. |
DefaultVal | Giá trị mặc định khi tạo record mới. |
TopEmpty | True → thêm option “Trống” ở đầu list. |
ComponentGroup | Reference tới ComponentGroup chứa picker. |
ComponentType | Sub-type (rare). |
Events kích hoạt
| Event | Method signature | Khi nào |
|---|---|---|
change | (entity, matched, oldMatch, parent) | User chọn 1 entity từ dropdown. |
AfterCreated | (entity) | Sau khi widget mount xong. |
AfterRender | (entity) | Sau khi render giá trị lên DOM. |
matched là entity tham chiếu vừa chọn (vd 1 Customer object), oldMatch cái cũ.
public void OnCustomerChanged(object entity, object matched, object oldMatch, object parent)
{
var invoice = (Invoice)entity;
var customer = matched as Customer;
if (customer != null)
{
invoice.CountryId = customer.CountryId; // auto-fill
this.FindComponentByName<SearchEntry>("Country")?.UpdateView();
}
}
Behavior
- Khi user gõ → query
Client.GetRawList<Customer>với filter ghépDataSourceFilter+ text user nhập trên các cột tìm kiếm cấu hình metadata. - Lưu
id(int) vàoentity.<FieldName>. - Cache result gần đây.
- Phím mũi tên phải mở popup picker (1 GridView của entity tham chiếu) — hữu ích khi cần filter nhiều cột.
Cấu hình cột cho popup picker (GridPolicy)
Khi user mở popup picker (phím mũi tên phải), Core render 1 GridView của entity tham chiếu (vd Customer). Cột của grid này lấy từ bảng GridPolicy theo rule:
Điều kiện row GridPolicy | Khi nào áp dụng |
|---|---|
FeatureId IS NULL | Default cho entity — áp cho mọi SearchEntry tham chiếu entity này. |
ComponentId = <Id picker> | Custom riêng cho row picker này — override default cho 1 picker cụ thể. |
Field tham chiếu entity là
EntityId(FK của bảng GridPolicy trỏ vàoEntitycủa entity tham chiếu — vdCustomer).
Workflow:
-
Mặc định: tạo các row
GridPolicyvớiFeatureId = NULL,ComponentId = NULL,EntityId = <Id của entity>(vd Customer). Mọi SearchEntry tham chiếuCustomerđều dùng các cột này. -
Custom cho 1 picker cụ thể: nếu picker A cần thêm/bớt cột so với default, tạo các row
GridPolicyriêng vớiComponentId = <Id của row Component picker A>. Core merge 2 nguồn theo logic ưu tiênComponentId>FeatureId IS NULL.
Ví dụ SQL:
-- Default cho Customer (mọi picker tham chiếu Customer đều thấy 3 cột này)
INSERT INTO GridPolicy (FeatureId, ComponentId, EntityId, FieldName, ShortDesc, Width, [Order]) VALUES
(NULL, NULL, /*Customer Id*/ 12, 'Code', N'Mã', '120', 10),
(NULL, NULL, 12, 'Name', N'Tên', '240', 20),
(NULL, NULL, 12, 'Phone', N'SĐT', '140', 30);
-- Custom thêm cột "Email" cho riêng picker A (Component Id = 999)
INSERT INTO GridPolicy (FeatureId, ComponentId, EntityId, FieldName, ShortDesc, Width, [Order]) VALUES
(NULL, 999, 12, 'Email', 'Email', '200', 25);
⚠ Đừng set
FeatureId = <Id feature đang edit>cho default GridPolicy của entity tham chiếu — đó là feature chứa picker, không phải entity tham chiếu. Quy tắc đúng:FeatureId IS NULLcho default toàn cục.
Picker cascade (filter theo entity hiện tại)
Dùng placeholder {<FieldName>} (curly braces) — runtime substitute giá trị từ entity:
DataSourceFilter: ?$filter=CustomerId eq {CustomerId}
→ Khi entity.CustomerId = 7, query thực tế ?$filter=CustomerId eq 7.
Hỗ trợ dotted path:
DataSourceFilter: ?$filter=CountryId eq {Customer.CountryId}
Tip
DataSourceFilterphải đủ?$filter=.... Sai → không load.- Clear field:
Esc+Enterhoặc codeentry.Value = null. - Bind code string thay vì id → dùng SearchEntryString.
- Multi-select → MultipleSearchEntry.