Giao diện
FAQ
Widget schema trả về rỗng dù đã save?
Nguyên nhân: getJsonSchema sử dụng cache. Nếu save thành công nhưng cache chưa invalidate, kết quả cũ (hoặc rỗng) sẽ được trả về.
Giải pháp:
- Gọi
uiWidgets:savequa API chuẩn (hook tự invalidate cache). - Nếu save trực tiếp DB, gọi explicit
clearCachetrên UiWidgetRepository. - Kiểm tra transaction có commit thành công chưa.
duplicate sinh UID mới như thế nào?
Khi duplicate, repository duyệt qua tất cả nodes trong subtree và sinh UID mới cho mỗi node. Mapping cũ → mới được duy trì để cập nhật references nội bộ (VD: link giữa button và target widget).
Biến template resolve sai giá trị?
Kiểm tra:
- Path đúng chưa? — biến phải đúng format
ctx.currentUser.id, không phảicurrentUser.id. - Resolver đã đăng ký? — VariableRegistry phải có resolver cho namespace (
ctx.currentUser,ctx.currentTime...). - Context request — biến
ctx.currentUsercần request có authentication (user đã đăng nhập).
Query chạy chậm hoặc timeout?
queryService:run và runById thực thi trực tiếp SQL trên data source.
- Kiểm tra query plan (EXPLAIN) trên database.
- Thêm index cho cột trong WHERE/JOIN.
- SQL Liquid variables được resolve trước khi thực thi — kiểm tra giá trị resolve có đúng không qua
variables:resolve.
mutate thất bại nhưng một số operations đã chạy?
mutate chạy trong transaction — nếu bất kỳ operation nào fail, toàn bộ batch sẽ rollback. Không có trường hợp "partial success".
Nếu gặp lỗi, kiểm tra:
- Operation nào gây lỗi (response sẽ chỉ ra).
- UID có tồn tại không (cho move/destroy).
- Schema validation có pass không (cho save — nếu widget type đã đăng ký).
Widget bị "mồ côi" (orphan) — không thuộc tree nào?
Xảy ra khi widget tồn tại trong uiWidgets nhưng không có record trong uiWidgetTreePath (hoặc chỉ có self-reference depth=0). Nguyên nhân thường do:
destroyparent nhưng không cascade.- Import dữ liệu thiếu closure paths.
Giải pháp: Gọi attach để gắn widget orphan vào một parent cụ thể.