Skip to Main Content
☕ Ủng hộ cafe

☕ Mời mình một ly cafe

Nếu tài liệu này hữu ích, bạn có thể ủng hộ mình một ly cafe để mình có thêm động lực viết tiếp ❤️

QR Support
Ngân hàng: VC Bank
Chủ tài khoản: DO KHAC LAM
Số tài khoản: 7906077097
Nội dung: Ung ho Dokhala
Cảm ơn bạn đã ủng hộ Dokhala 🙏
💬 Liên hệ

💬 Kết nối với mình

Bạn cần hỏi thêm về Oracle APEX, góp ý nội dung, hoặc muốn trao đổi dự án? Có thể nhắn mình qua các kênh dưới đây.

← Quay lại bài viết

Xây dựng CSS + Template Directive Pattern Library trong Oracle APEX

Tìm hiểu cách xây dựng một pattern library nhỏ trong Oracle APEX bằng CSS và Template Directives để tái sử dụng badge, tag, empty state, action link và priority style trong Cards, Reports và Email Templates.

Khi ứng dụng Oracle APEX bắt đầu có nhiều page, nhiều report và nhiều card, một vấn đề rất dễ xuất hiện là giao diện bị thiếu nhất quán. Mỗi developer có thể viết một kiểu badge, một kiểu link, một kiểu tag, hoặc một cách hiển thị trạng thái khác nhau.

Ban đầu điều này có vẻ không nghiêm trọng. Nhưng sau vài tháng, app sẽ có nhiều đoạn HTML/CSS lặp lại, khó bảo trì và khó thay đổi đồng bộ. Nếu muốn đổi màu badge trạng thái hoặc chuẩn hóa cách hiển thị “Không có dữ liệu”, bạn phải tìm và sửa ở rất nhiều nơi.

Một cách làm gọn hơn là xây dựng một CSS + Template Directive Pattern Library cho chính ứng dụng APEX của bạn. Hiểu đơn giản, đây là một bộ pattern nhỏ gồm CSS dùng chung và các đoạn Template Directive mẫu để áp dụng lại trong Cards, Classic Reports, Interactive Reports, Interactive Grid hoặc Email Templates.

Pattern Library trong APEX là gì?

Pattern Library không cần phải là một design system lớn và phức tạp. Với Oracle APEX, bạn có thể bắt đầu bằng một file CSS nhỏ và vài mẫu Template Directive thường dùng.

Ví dụ:

  • Badge trạng thái: Active, Inactive, Cancelled, Draft, Published.
  • Boolean flag: Yes/No, Enabled/Disabled.
  • Action link theo quyền: Edit nếu có quyền, View only nếu không có quyền.
  • Empty state: hiển thị text nhẹ nhàng khi dữ liệu trống.
  • Tag: hiển thị nhiều nhãn nhỏ.
  • Priority accent: đánh dấu mức độ ưu tiên cao, trung bình, thấp.

Khi các pattern này được chuẩn hóa, bạn chỉ cần dùng lại cùng class CSS và cùng cấu trúc directive. Giao diện sẽ nhất quán hơn, SQL gọn hơn và việc bảo trì cũng dễ hơn.

Thêm CSS dùng chung một lần cho toàn app

Bước đầu tiên là định nghĩa các class CSS dùng chung. Bạn có thể thêm CSS trong Theme Roller, Custom CSS hoặc lưu thành static file rồi include vào app.

Thêm CSS pattern library trong Oracle APEX
Ví dụ nơi thêm CSS dùng chung cho pattern library trong Oracle APEX.

Ví dụ bộ CSS cơ bản:

/* ===== Badges ===== */
.dk-badge {
  display: inline-flex;
  align-items: center;
  border-radius: 999px;
  padding: 0.3rem 0.65rem;
  font-size: 0.75rem;
  font-weight: 800;
  line-height: 1;
  white-space: nowrap;
}

.dk-badge-success {
  background: #eef7f1;
  color: #006b4f;
}

.dk-badge-warning {
  background: #fff7df;
  color: #8a6100;
}

.dk-badge-danger {
  background: #fdecec;
  color: #a50e0e;
}

.dk-badge-info {
  background: #e8f0fe;
  color: #1a5fb4;
}

.dk-badge-muted {
  background: #f1f3f4;
  color: #5f6368;
}

/* ===== Links ===== */
.dk-action-link {
  color: #006b4f;
  text-decoration: none;
  font-weight: 800;
}

.dk-action-link:hover {
  color: #f2a900;
  text-decoration: underline;
}

/* ===== Empty State ===== */
.dk-empty {
  color: #7a8a84;
  font-style: italic;
}

/* ===== Tags ===== */
.dk-tag {
  display: inline-flex;
  align-items: center;
  margin: 0 4px 4px 0;
  padding: 0.25rem 0.55rem;
  border-radius: 999px;
  font-size: 0.72rem;
  font-weight: 700;
  background: #f1f5f3;
  color: #003c35;
}

/* ===== Priority Accents ===== */
.dk-priority-high {
  border-left: 4px solid #d93025;
  padding-left: 8px;
}

.dk-priority-medium {
  border-left: 4px solid #f2a900;
  padding-left: 8px;
}

.dk-priority-low {
  border-left: 4px solid #188038;
  padding-left: 8px;
}

Bộ CSS này cố tình đơn giản. Mục tiêu không phải tạo hiệu ứng phức tạp, mà là tạo các class dễ hiểu, dễ dùng lại và phù hợp với Universal Theme.

Pattern 1: Status Badge

Trạng thái là một trong những thứ xuất hiện nhiều nhất trong ứng dụng APEX: đơn hàng, task, ticket, bài viết, người dùng, thanh toán, approval request...

Thay vì viết HTML trong SQL, bạn có thể để SQL trả về cột STATUS, rồi dùng Template Directive để render badge.

{case STATUS/}
  {when ACTIVE/}
    <span class="dk-badge dk-badge-success">Active</span>
  {when INACTIVE/}
    <span class="dk-badge dk-badge-warning">Inactive</span>
  {when CANCELLED/}
    <span class="dk-badge dk-badge-danger">Cancelled</span>
  {otherwise/}
    <span class="dk-badge dk-badge-muted">Unknown</span>
{endcase/}

Pattern này có thể dùng trong Cards, Classic Report, Interactive Report hoặc Email Template. Điểm hay là nếu sau này muốn đổi màu badge, bạn chỉ cần sửa CSS.

Pattern 2: Boolean Flag

Với các cột kiểu Y/N, 1/0, TRUE/FALSE, bạn thường muốn hiển thị thành badge dễ đọc hơn.

{if FLAG/}
  <span class="dk-badge dk-badge-success">Yes</span>
{else/}
  <span class="dk-badge dk-badge-muted">No</span>
{endif/}

Pattern này phù hợp cho các trường như active flag, verified flag, published flag, paid flag hoặc enabled flag.

Pattern 3: Action Link theo quyền

Trong nhiều ứng dụng, không phải user nào cũng có quyền chỉnh sửa. Bạn có thể dùng một cột như CAN_EDIT để quyết định hiển thị link Edit hoặc chỉ hiển thị trạng thái View only.

{if CAN_EDIT/}
  <a class="dk-action-link"
     href="f?p=&APP_ID.:10:&SESSION.::NO::P10_ID:&ID.">
    Edit
  </a>
{else/}
  <span class="dk-empty">View only</span>
{endif/}

Lưu ý quan trọng: directive này chỉ điều khiển giao diện. Quyền thật vẫn phải được kiểm tra bằng Authorization Scheme hoặc PL/SQL ở phía server. Không nên xem việc ẩn link trên UI là một cơ chế bảo mật đầy đủ.

Pattern 4: Empty State

Dữ liệu trống không nên hiển thị thành khoảng trắng khó hiểu. Với các field như phone, note, description hoặc assignee, bạn có thể hiển thị text nhẹ nhàng hơn.

{if DESCRIPTION/}
  &DESCRIPTION.
{else/}
  <span class="dk-empty">Chưa có mô tả</span>
{endif/}

Empty state nhỏ nhưng giúp giao diện dễ hiểu hơn, nhất là với report có nhiều cột optional.

Pattern 5: Tags

Tags thường dùng trong blog, task, ticket, sản phẩm hoặc tài liệu. Nếu dữ liệu tag được lưu dạng danh sách phân tách bằng dấu phẩy, bạn có thể dùng loop directive.

{loop "," TAGS/}
  <span class="dk-tag">&APEX$ITEM.</span>
{endloop/}

Với pattern này, một cột TAGS như:

APEX,AI,PLSQL

có thể được render thành nhiều tag nhỏ trong UI.

Pattern 6: Priority Accent

Một số dữ liệu cần được nhấn mạnh bằng đường viền hoặc màu sắc nhẹ: high priority, overdue, urgent, warning...

<div class="
  {case PRIORITY/}
    {when HIGH/}dk-priority-high
    {when MEDIUM/}dk-priority-medium
    {when LOW/}dk-priority-low
  {endcase/}
">
  <strong>&TITLE.</strong>
  {if SUMMARY/}
    <p>&SUMMARY.</p>
  {endif/}
</div>

Pattern này giúp người dùng quét thông tin nhanh hơn mà không cần đọc toàn bộ nội dung.

Ví dụ kết quả trong Oracle APEX

Sau khi thêm CSS và áp dụng Template Directives, giao diện report hoặc card sẽ có các badge, tag và link rõ ràng hơn. Điều quan trọng là SQL vẫn giữ được sự đơn giản.

Kết quả CSS Template Directive Pattern Library trong Oracle APEX
Kết quả mong muốn: badge, tag, empty state và action link nhất quán trên giao diện APEX.

SQL nên giữ đơn giản

Một nguyên tắc tốt là SQL chỉ nên trả dữ liệu thô hoặc dữ liệu đã chuẩn hóa, không nên chứa quá nhiều HTML.

select id,
       title,
       status,
       priority,
       tags,
       summary,
       case
         when :APP_USER = owner_username then 'Y'
         else null
       end as can_edit
from project_tasks;

Sau đó, phần template quyết định STATUS thành badge nào, PRIORITY thành accent nào và CAN_EDIT thành link hay text.

Pattern Library giúp làm việc nhóm tốt hơn

Khi làm một mình, bạn có thể nhớ mình đã dùng class nào. Nhưng khi app có nhiều người cùng phát triển, việc chuẩn hóa pattern trở nên rất quan trọng.

Bạn nên tạo một tài liệu nhỏ trong project, ví dụ:

docs/ui-patterns.md

Trong đó ghi rõ:

  • Class nào dùng cho badge thành công, cảnh báo, lỗi.
  • Template Directive nào dùng cho status.
  • Pattern nào dùng cho action link.
  • Pattern nào dùng cho tag.
  • Khi nào được dùng raw HTML và khi nào không.

Cách này giúp developer mới vào dự án có thể làm UI đồng nhất với phần còn lại của ứng dụng.

Lưu ý về bảo mật và escaping

Template Directives giúp giảm việc nối HTML trong SQL, nhưng không có nghĩa là bạn có thể bỏ qua escaping. Nếu dữ liệu đến từ người dùng, hãy đảm bảo dữ liệu đó được escape đúng context.

Một số nguyên tắc nên giữ:

  • Không render HTML người dùng nhập nếu không sanitize.
  • Không dùng raw output cho dữ liệu không đáng tin cậy.
  • Không dùng directive để thay thế authorization.
  • Không đưa logic nghiệp vụ quan trọng vào template.
  • Luôn kiểm tra quyền ở server-side.

Template Directive là công cụ trình bày, không phải lớp bảo mật.

Kết luận

CSS + Template Directive Pattern Library là một cách rất thực tế để chuẩn hóa giao diện Oracle APEX. Bạn không cần xây design system phức tạp. Chỉ cần bắt đầu với vài pattern dùng thường xuyên: badge, tag, empty state, action link và priority accent.

Khi CSS được thêm một lần và Template Directives được dùng đúng chỗ, ứng dụng APEX sẽ gọn hơn, dễ bảo trì hơn và chuyên nghiệp hơn.