Ở các phần trước, chúng ta đã tạo cấu trúc nội dung cho website nhà sách trong Umbraco CMS. Website hiện có một node gốc Bookstore Home và các danh mục như Lịch sử và Triết học.
Tuy nhiên, việc tạo danh mục trong Backoffice mới chỉ là bước đầu. Khi xây dựng website thực tế, chúng ta cần lấy các danh mục này để tạo menu điều hướng. Nếu tên danh mục thay đổi hoặc biên tập viên thêm một danh mục mới, menu nên phản ánh những thay đổi đó mà không cần lập trình viên sửa code mỗi lần.
Trong bài thực hành này, chúng ta sẽ tìm hiểu cách sử dụng Content Tree và Content Delivery API để lấy dữ liệu danh mục, sau đó xác định cấu trúc JSON phù hợp cho menu.
Mục tiêu của bài viết:
- Hiểu mối liên hệ giữa Content Tree và menu điều hướng.
- Lấy các node con của Bookstore Home bằng Content Delivery API.
- Đọc JSON response và xác định dữ liệu cần dùng cho menu.
- Phân biệt dữ liệu API trả về với cấu trúc menu mà frontend cần.
- Chuẩn bị dữ liệu để tích hợp menu vào Next.js ở phần tiếp theo.
1. Từ Content Tree đến menu website
1.1. Cấu trúc nội dung trong Umbraco
Giả sử Content Tree của website nhà sách có cấu trúc như sau:
Content
└── Bookstore Home
├── Lịch sử
└── Triết học
Trong đó:
- Bookstore Home: node gốc của website nhà sách.
- Lịch sử: danh mục sách về lịch sử.
- Triết học: danh mục sách về triết học.
Content Tree biểu diễn quan hệ cha–con giữa các content item. Đây là cấu trúc mà chúng ta có thể sử dụng để xác định những mục sẽ xuất hiện trên menu.
1.2. Menu trên website sẽ trông như thế nào?
Với cấu trúc hiện tại, menu mong muốn có thể đơn giản như sau:
Nhà sách
├── Lịch sử
└── Triết học
Khi người dùng nhấn vào Lịch sử, website sẽ điều hướng đến trang danh mục Lịch sử. Tương tự, mục Triết học sẽ dẫn đến trang danh mục tương ứng.
Điểm quan trọng là tên và đường dẫn của menu nên được lấy từ dữ liệu nội dung, thay vì viết cố định trực tiếp trong frontend.
1.3. Kiến trúc dữ liệu
Trong kiến trúc này, Umbraco chịu trách nhiệm quản lý nội dung. Content Delivery API cung cấp nội dung đã publish dưới dạng JSON. Frontend sử dụng JSON để xây dựng menu và quyết định cách hiển thị.
2. Chuẩn bị nội dung trong Backoffice
Trước khi gọi API, hãy mở Umbraco Backoffice và kiểm tra cấu trúc Content Tree.
- Mở node Bookstore Home.
- Xác nhận node Lịch sử và Triết học nằm bên dưới node này.
- Kiểm tra các node cần hiển thị trên menu đã được publish.
- Kiểm tra đường dẫn thực tế của từng node trong phần thông tin của content item.
Lưu ý: tên hiển thị trong Backoffice có thể khác URL segment và alias của Document Type. Không nên tự suy đoán URL từ tên tiếng Việt; hãy kiểm tra route thực tế trong project.
3. Lấy các node con bằng Content Delivery API
3.1. Endpoint truy vấn nhiều content item
Content Delivery API của Umbraco 13 cung cấp endpoint truy vấn danh sách content item:
GET /umbraco/delivery/api/v2/content
Endpoint này hỗ trợ tham số fetch để truy vấn nội dung dựa trên cấu trúc Content Tree. Để lấy các node con trực tiếp của node gốc (Trang chủ), chúng ta sử dụng selector children: kết hợp với GUID hoặc Path:
- Truy vấn theo GUID (Khuyên dùng - Chuẩn xác nhất):
GET /umbraco/delivery/api/v2/content?fetch=children:256048db-162d-4cc7-b7e3-c4537fb970bd - Truy vấn theo Path (Trang chủ có route /):
GET /umbraco/delivery/api/v2/content?fetch=children:/
Lưu ý: GUID của node trang chủ (256048db-162d-4cc7-b7e3-c4537fb970bd) có thể lấy trong tab Info (Thông tin) của node Bookstore Home ở Umbraco Backoffice. Tham số fetch=children:... chỉ lấy các node con trực tiếp cấp 1, không tự động lấy toàn bộ cây con nhiều cấp.
3.2. Thực hành gọi API trên Swagger UI
Mở Swagger UI của ứng dụng Umbraco trong môi trường Development:
https://localhost:44366/umbraco/swagger
Các bước thực hiện:
- Tìm và mở endpoint
GET /umbraco/delivery/api/v2/content. - Nhấn nút Try it out.
- Tại tham số
fetch:- Chọn dropdown mẫu Examples → chọn Select all children of a node by id (hoặc by path).
- Nhập giá trị thực tế vào ô input bên dưới:
children:256048db-162d-4cc7-b7e3-c4537fb970bd(hoặcchildren:/). - Lưu ý: Khi bạn tự gõ hoặc chỉnh sửa nội dung ô input, dropdown Examples sẽ tự động chuyển nhãn thành
[Modified value]— đây là phản hồi bình thường của Swagger UI xác nhận giá trị tùy chỉnh của bạn đã được ghi nhận.
- Nhập
Api-Keyvào header nếu project có yêu cầu xác thực. - Nhấn Execute và kiểm tra HTTP status cùng JSON response.
Cách kiểm tra kết quả: Nếu API trả về mã HTTP 200, kiểm tra mảng "items" trong JSON response. Bạn sẽ thấy danh sách các danh mục con trực tiếp (như Lịch sử, Triết học) nằm bên dưới node Trang chủ.
4. Đọc JSON response
4.1. Ví dụ response minh họa
Giả sử API trả về danh sách content item có cấu trúc tương tự ví dụ rút gọn dưới đây:
{
"total": 2,
"items": [
{
"contentType": "bookCategory",
"name": "Lịch sử",
"route": {
"path": "/lich-su/"
},
"id": "00000000-0000-0000-0000-000000000001",
"properties": {
"categoryTitle": "Lịch sử"
}
},
{
"contentType": "bookCategory",
"name": "Triết học",
"route": {
"path": "/triet-hoc/"
},
"id": "00000000-0000-0000-0000-000000000002",
"properties": {
"categoryTitle": "Triết học"
}
}
]
}
Đây là JSON giả lập để minh họa cách đọc dữ liệu, không phải response nguyên bản được bảo đảm của Umbraco 13. Tên trường, đường dẫn, GUID, alias và giá trị property trong project của bạn có thể khác. Hãy dùng JSON thực tế thu được từ Swagger để triển khai.
4.2. Những trường cần quan tâm
| Trường | Ý nghĩa | Sử dụng cho menu |
|---|---|---|
name |
Tên content item. | Làm nhãn menu nếu phù hợp. |
route.path |
Đường dẫn của content item. | Dùng làm cơ sở tạo URL điều hướng. |
contentType |
Alias của Document Type. | Giúp phân biệt loại nội dung. |
id |
GUID của content item. | Hữu ích khi cần tham chiếu đến item. |
properties |
Các property được trả về. | Có thể cung cấp tên menu hoặc tùy chọn hiển thị nếu được cấu hình. |
Không nên giả định rằng mọi Document Type đều có property categoryTitle. Nếu project chỉ sử dụng tên node trong Backoffice, trường name có thể đã đủ cho menu cơ bản.
5. Từ JSON API đến cấu trúc menu
5.1. Không nên dùng nguyên JSON API làm model giao diện
Response của Content Delivery API được thiết kế để biểu diễn content item của Umbraco. Trong khi đó, menu frontend thường chỉ cần một số thông tin như nhãn, URL và các mục con.
Vì vậy, chúng ta có thể ánh xạ dữ liệu API sang một cấu trúc menu đơn giản hơn:
[
{
"label": "Lịch sử",
"href": "/lich-su/",
"children": []
},
{
"label": "Triết học",
"href": "/triet-hoc/",
"children": []
}
]
Cấu trúc này chỉ là model dành cho frontend. Nó không phải format mặc định mà Content Delivery API trả về.
5.2. Quy tắc ánh xạ dữ liệu
Khi viết hàm chuyển JSON API thành dữ liệu menu, ta có thể áp dụng các quy tắc sau:
labellấy từnamehoặc một property dành riêng cho nhãn menu.hreflấy từ route thực tế của content item.childrenchứa các mục menu con nếu ứng dụng đã truy vấn và ánh xạ những node đó.- Chỉ đưa vào menu những content item đáp ứng quy tắc hiển thị của website.
Ví dụ, nếu sau này Bookstore Home có thêm danh mục Văn học và danh mục đó được publish, menu có thể cập nhật theo dữ liệu mới mà không cần viết thêm một mục menu cố định trong frontend.
Tuy nhiên, để điều này hoạt động, ứng dụng cần truy vấn và ánh xạ lại dữ liệu phù hợp. Chỉ tạo một node mới trong Backoffice không có nghĩa là mọi frontend sẽ tự cập nhật ngay lập tức; kết quả còn phụ thuộc vào cache, cơ chế fetch và thời điểm build của ứng dụng.
6. Xử lý menu nhiều cấp
Hiện tại website chỉ có hai danh mục cấp đầu tiên. Trong tương lai, Content Tree có thể mở rộng như sau:
Bookstore Home
├── Lịch sử
│ ├── Lịch sử Việt Nam
│ └── Lịch sử Trung Quốc
└── Triết học
├── Triết học phương Đông
└── Triết học phương Tây
Để xây dựng menu nhiều cấp, cần lấy thêm các node con của từng danh mục hoặc sử dụng một truy vấn phù hợp để lấy các node descendants, sau đó xây dựng quan hệ cha–con trong model menu.
Không nên mặc định rằng một request lấy Bookstore Home sẽ tự động trả về toàn bộ cây con theo dạng đệ quy. Hãy kiểm tra response và chọn cách truy vấn phù hợp với yêu cầu thực tế.
Đối với website lớn, cũng cần cân nhắc số lượng request, giới hạn dữ liệu trả về, phân trang, cache và cách xử lý các danh mục không được phép hiển thị trên menu.
7. Những vấn đề cần lưu ý
7.1. Node chưa publish
Content Delivery API chủ yếu cung cấp nội dung đã publish. Nếu một danh mục mới chỉ được lưu nháp, nó có thể không xuất hiện trong response thông thường.
7.2. Sai đường dẫn hoặc GUID
Tham số fetch cần tham chiếu đúng content item. Nếu kết quả rỗng hoặc API trả lỗi, hãy kiểm tra lại đường dẫn hoặc GUID của Bookstore Home.
7.3. API Key
Nếu Delivery API đã được cấu hình để yêu cầu API Key, request phải gửi đúng header Api-Key. Không đưa API Key bí mật vào JavaScript chạy trên trình duyệt hoặc biến môi trường có tiền tố NEXT_PUBLIC_. Khi tích hợp với Next.js, hãy xử lý khóa bí mật ở phía server.
7.4. API trả về dữ liệu nhưng menu không hiển thị
Nếu JSON đã có dữ liệu nhưng menu chưa hiển thị, cần kiểm tra riêng phần ánh xạ trường dữ liệu, URL, điều kiện lọc và code render của frontend.
Hãy kiểm tra API độc lập trước. Việc này giúp phân biệt lỗi phía Umbraco với lỗi trong ứng dụng frontend.
8. Bài tập thực hành
Bài tập 1: Lấy danh mục cấp đầu tiên
- Gọi endpoint Content Delivery API với selector
fetch=childrencho Bookstore Home. - Kiểm tra response có các node Lịch sử và Triết học hay không.
- Ghi lại tên node, route và content type alias thực tế.
Bài tập 2: Thiết kế model menu
Từ JSON thực tế, tự tạo một JSON riêng chỉ chứa những trường cần thiết cho menu, chẳng hạn:
[
{
"label": "Tên danh mục",
"href": "/duong-dan-danh-muc/",
"children": []
}
]
Thay các giá trị ví dụ bằng dữ liệu thực tế của project.
Bài tập 3: Kiểm tra khả năng mở rộng
- Thêm một danh mục thử nghiệm trong môi trường Development.
- Publish danh mục đó.
- Gọi lại API và kiểm tra danh sách node con.
- Xác định các bước cần thiết để model menu nhận được danh mục mới.
9. Checklist hoàn thành Day 3.1
- Hiểu mối liên hệ giữa Content Tree và menu điều hướng.
- Biết cách truy vấn các node con bằng Content Delivery API.
- Đọc được tên node, route và content type alias trong JSON.
- Phân biệt JSON response của Umbraco với model menu của frontend.
- Biết rằng menu nhiều cấp cần xử lý thêm quan hệ cha–con.
- Biết kiểm tra trạng thái publish, API Key và lỗi truy vấn.
10. Tổng kết và bước tiếp theo
Qua bài thực hành này, chúng ta đã kết nối ba khái niệm: Content Tree, Content Delivery API và menu điều hướng.
Ba ý quan trọng cần ghi nhớ:
- Content Tree tổ chức các content item theo quan hệ cha–con.
- Content Delivery API cung cấp dữ liệu nội dung dưới dạng JSON; selector
childrencó thể được dùng để truy vấn các node con trực tiếp. - Frontend chịu trách nhiệm chuyển JSON thành model menu và render giao diện.
Ở phần tiếp theo, chúng ta sẽ kết nối Umbraco với Next.js, gọi Content Delivery API từ phía server và sử dụng dữ liệu nhận được để hiển thị menu trên website. Đây là bước chuyển từ việc kiểm tra API độc lập sang xây dựng một ứng dụng Headless CMS hoàn chỉnh hơn.
Nhận xét