Nhảy đến nội dung

Giới thiệu

Định nghĩa các trường tùy chỉnh cho nội dung của bạn mà không cần chạm vào mã.

🎯 Mô-đun này làm gì?

Mô-đun AttributesSets cho phép bạn sử dụng các trường tùy chỉnh cho nội dung của bạn (sản phẩm, trang, biểu mẫu, v.v.) mà không cần mã hóa chúng trong ứng dụng của bạn.

Hãy nghĩ về nó như một trình tạo biểu mẫu cho dữ liệu của bạn - bạn định nghĩa các trường bạn cần, và OneEntry sẽ xử lý phần còn lại.

📖 Giải thích đơn giản

Hãy tưởng tượng bạn đang xây dựng một cửa hàng trực tuyến. Mỗi sản phẩm cần:

  • Tên (văn bản)
  • Giá (số)
  • Hình ảnh (hình ảnh)
  • Mô tả (văn bản dài)
  • Danh mục (thả xuống)

Thay vì mã hóa cứng các trường này trong ứng dụng của bạn, bạn sử dụng Attributes để định nghĩa chúng trong bảng điều khiển quản trị OneEntry. Sau đó, bạn có thể:

  • ✅ Thêm các trường mới bất cứ lúc nào (không cần thay đổi mã!)
  • ✅ Tái sử dụng các trường trên nhiều loại nội dung khác nhau
  • ✅ Thay đổi loại trường mà không cần triển khai lại
  • ✅ Quản lý toàn bộ cấu trúc nội dung ở một nơi

Ví dụ thực tế:

Không có Attributes (mã cứng):
- Mã: const product = { name, price, image, description }
- Để thêm trường "màu sắc" → Thay đổi mã, triển khai lại, chờ ❌

Với Attributes (động):
- Bảng điều khiển quản trị: Thêm thuộc tính "màu sắc"
- Mã tự động bao gồm trường mới ✅
- Không cần triển khai! ✅

✨ Khái niệm chính

Thuộc tính là gì?

Một thuộc tính là một trường đơn lẻ lưu trữ dữ liệu.

Ví dụ:

  • Tên sản phẩm (chuỗi)
  • Giá sản phẩm (số thực)
  • Hình ảnh sản phẩm (hình ảnh)
  • Ngày xuất bản (ngày)

Bộ thuộc tính là gì?

Một bộ thuộc tính là một tập hợp các thuộc tính định nghĩa một cấu trúc.

Ví dụ: Bộ thuộc tính sản phẩm

- name (chuỗi)
- price (số thực)
- description (văn bản)
- images (nhóm hình ảnh)
- category (danh sách)
- inStock (số nguyên)

Tại sao nên sử dụng bộ thuộc tính?

Không có AttributesCó Attributes
❌ Trường mã cứng✅ Trường động
❌ Cần thay đổi mã✅ Chỉnh sửa trong bảng điều khiển
❌ Cần triển khai lại✅ Cập nhật trực tiếp
❌ Cấu trúc cứng✅ Cấu trúc linh hoạt
❌ Mã trùng lặp✅ Bộ có thể tái sử dụng

📋 Những điều bạn cần biết

Ba thuật ngữ quan trọng

Thuật ngữĐịnh nghĩaVí dụ
MarkerMã định danh duy nhất"product_name"
TypeLoại dữ liệu mà nó lưu trữ"string", "integer", "image"
ValueGiá trị thuộc tính"Tên sản phẩm"

Điều quan trọng về Markers:

  • Phải duy nhất
  • Không cho phép khoảng trắng (sử dụng _ thay thế)
  • Không thể bắt đầu bằng số
  • Sử dụng chữ thường để nhất quán

Ví dụ:

  • ✅ Tốt: product_name, price_usd, main_image
  • ❌ Xấu: product name, 2nd_price, Product Name

Tính tái sử dụng

Các bộ thuộc tính có thể được tái sử dụng trên nhiều thực thể khác nhau:

Bộ thuộc tính "Thông tin cơ bản":
- title (chuỗi)
- description (văn bản)
- publish_date (ngày)

Được sử dụng bởi:
✅ Bài viết blog
✅ Bài báo tin tức
✅ Trang sản phẩm
✅ Danh sách sự kiện

Tại sao điều này quan trọng: Thay đổi một lần, cập nhật ở mọi nơi!


📚 Các loại dữ liệu có sẵn

Các thuộc tính có thể lưu trữ các loại dữ liệu khác nhau. Chọn loại phù hợp cho mỗi trường.

Bảng tham khảo nhanh

LoạiTốt nhất choVí dụ sử dụng
stringVăn bản ngắnTên sản phẩm, email
textVăn bản dài có định dạngBài viết blog, mô tả
textWithHeaderVăn bản có tiêu đềCác phần của bài viết
integerSố nguyênSố lượng, tuổi
realSố thập phân chính xác caoDữ liệu khoa học
floatSố thập phânGiá, đánh giá
dateChỉ ngàyNgày sinh, hạn chót
dateTimeNgày + giờThời gian sự kiện, xuất bản lúc
timeChỉ giờGiờ mở cửa
fileBất kỳ tệp nàoPDF, tài liệu
imageHình ảnh đơnẢnh đại diện, logo
groupOfImagesNhiều hình ảnhThư viện ảnh
radioButtonLựa chọn đơnKích thước (S/M/L)
listLựa chọn thả xuốngQuốc gia, danh mục
entityLiên kết đến nội dung khácSản phẩm liên quan
timeIntervalKhoảng thời gianThời gian khuyến mãi
jsonDữ liệu có cấu trúc tùy chỉnhPhản hồi API

🔍 Mô tả chi tiết về các loại dữ liệu

Các loại văn bản

Khi nào sử dụng cái gì:

  • string - Dòng đơn, dưới 255 ký tự (tên, email, tiêu đề)
  • text - Nhiều đoạn văn, hỗ trợ định dạng (bài viết, mô tả)
  • textWithHeader - Văn bản cần tiêu đề (các phần của blog, Câu hỏi thường gặp)

Các loại số

Khi nào sử dụng cái gì:

  • integer - Không cần số thập phân (tuổi, số lượng, lượt xem)
  • float - Số thập phân tiêu chuẩn (giá $19.99, đánh giá 4.5)
  • real - Cần độ chính xác cao hơn (tính toán khoa học)

Các loại ngày/giờ

Khi nào sử dụng cái gì:

  • date - Chỉ ngày (sinh nhật, hạn chót)
  • time - Chỉ giờ (giờ làm việc, thời gian hẹn)
  • dateTime - Cả hai đều cần (thời gian sự kiện, bài viết đã xuất bản)
  • timeInterval - Khoảng thời gian giữa các ngày (thời gian khuyến mãi, ngày nghỉ)

Các loại tệp & hình ảnh

Khi nào sử dụng cái gì:

  • file - Bất kỳ tài liệu nào (PDF, DOC, ZIP)
  • image - Một bức ảnh (ảnh sản phẩm, ảnh đại diện)
  • groupOfImages - Nhiều bức ảnh (thư viện, hình ảnh sản phẩm)

Các loại lựa chọn

Khi nào sử dụng cái gì:

  • radioButton - Chọn chỉ MỘT tùy chọn (Có/Không, Kích thước S/M/L)
  • list - Thả xuống với các tùy chọn (Quốc gia, Danh mục, Trạng thái)

Các loại nâng cao

  • entity - Liên kết đến các trang/sản phẩm khác (Mặt hàng liên quan, Danh mục)
  • json - Lưu trữ cấu trúc dữ liệu phức tạp (phản hồi API, cài đặt)

📖 Ví dụ về các loại dữ liệu

Dưới đây là các ví dụ kỹ thuật về cấu trúc của từng loại dữ liệu.

Nhấp để xem tất cả các ví dụ về loại dữ liệu

Tham khảo các loại dữ liệu

Các loại dữ liệu có thể là các loại sau:

  • String: Văn bản đơn giản, ví dụ, "Xin chào, thế giới!".

Ví dụ:

{
"type": "string",
"value": {},
"marker": "string",
"position": 1,
"listTitles": [],
"validators": {
"requiredValidator": {
"strict": true
}
},
"localizeInfos": {
"title": "String"
},
"additionalFields": [
{
"type": "integer",
"value": "10",
"marker": "Extra"
}
]
}

  • Text: Văn bản dài hơn, thường được định dạng, ví dụ, một bài viết hoặc một bức thư.

Ví dụ:

{
"type": "text",
"value": {},
"marker": "text",
"position": 2,
"listTitles": [],
"validators": {},
"localizeInfos": {
"title": "Text"
},
"additionalFields": []
}

  • Text with Header: Văn bản có tiêu đề có thể được sử dụng để chỉ định một chủ đề hoặc danh mục.

Ví dụ:

{
"type": "textWithHeader",
"value": {},
"marker": "text_with_header",
"position": 3,
"listTitles": [],
"validators": {},
"localizeInfos": {
"title": "Text With Header"
},
"additionalFields": []
}

  • Integer: Một số nguyên, ví dụ, 5, 100, -2.

Ví dụ:

{
"type": "integer",
"value": {},
"marker": "integer",
"position": 4,
"listTitles": [],
"validators": {},
"localizeInfos": {
"title": "Integer"
},
"additionalFields": []
}

  • Real: Giống như Float, nhưng với độ chính xác cao hơn.

Ví dụ:

{
"type": "real",
"value": {},
"marker": "real_number",
"position": 5,
"listTitles": [],
"validators": {},
"localizeInfos": {
"title": "Real Number"
},
"additionalFields": []
}

  • Float: Một loại dữ liệu cho các số thập phân có thể có phần thập phân, ví dụ, 3.14, 1.5, -0.25.

Ví dụ:

{
"type": "float",
"value": {},
"marker": "float",
"position": 6,
"listTitles": [],
"validators": {},
"localizeInfos": {
"title": "Float"
},
"additionalFields": []
}

  • Date and Time: Một sự kết hợp của ngày và giờ, ví dụ, 2023-10-27 10:00:00.

Ví dụ:

{
"type": "dateTime",
"value": {},
"marker": "date_time",
"position": 7,
"listTitles": [],
"validators": {},
"localizeInfos": {
"title": "DateTime"
},
"additionalFields": []
}

  • Date: Một ngày, ví dụ, 2023-10-27.

Ví dụ:

{
"type": "date",
"value": {},
"marker": "date",
"position": 8,
"listTitles": [],
"validators": {},
"localizeInfos": {
"title": "Date"
},
"additionalFields": []
}

  • Time: Một thời gian, ví dụ, 10:00:00.

Ví dụ:

{
"type": "date",
"value": {},
"marker": "date",
"position": 8,
"listTitles": [],
"validators": {},
"localizeInfos": {
"title": "Date"
},
"additionalFields": []
}

  • File: Bất kỳ tệp nào trên máy tính của bạn, ví dụ, một tài liệu, hình ảnh, nhạc.

Ví dụ:

{
"type": "file",
"value": {},
"marker": "file",
"position": 10,
"listTitles": [],
"validators": {
"checkingFilesValidator": {
"maxUnits": "kb",
"maxValue": "2000",
"minUnits": "kb",
"minValue": 0,
"extensions": []
}
},
"localizeInfos": {
"title": "File"
},
"additionalFields": []
}

  • Image: Một hình ảnh, ví dụ, một bức ảnh, một bức tranh.

Ví dụ:

{
"type": "image",
"value": {},
"marker": "image",
"position": 11,
"listTitles": [],
"validators": {
"sizeInPixelsValidator": {
"maxX": "500",
"maxY": "500"
}
},
"localizeInfos": {
"title": "Image"
},
"additionalFields": []
}

  • Group of Images: Một tập hợp các hình ảnh, ví dụ, một album ảnh.

Ví dụ:

{
"type": "groupOfImages",
"value": {},
"marker": "image_group",
"position": 12,
"listTitles": [],
"validators": {},
"localizeInfos": {
"title": "Image Group"
},
"additionalFields": []
}

  • Radio Button: Một nút lựa chọn mà chỉ có thể chọn một tùy chọn.

Ví dụ:

{
"type": "radioButton",
"value": {},
"marker": "radio",
"position": 13,
"listTitles": [
{
"title": "A",
"value": "a",
"extended": {
"type": null,
"value": null
},
"position": 1
},
{
"title": "B",
"value": "b",
"extended": {
"type": null,
"value": null
},
"position": 2
}
],
"validators": {},
"localizeInfos": {
"title": "Radio"
},
"additionalFields": []
}

  • List: Một danh sách các mục, ví dụ, một danh sách mua sắm.

Ví dụ:

{
"type": "list",
"value": {},
"marker": "list",
"position": 14,
"listTitles": [
{
"title": "A",
"value": "a",
"extended": {
"type": null,
"value": null
},
"position": 1
},
{
"title": "B",
"value": "b",
"extended": {
"type": null,
"value": null
},
"position": 2
},
{
"title": "C",
"value": "c",
"extended": {
"type": "string",
"value": "Giá trị bổ sung"
},
"position": 3
}
],
"validators": {},
"localizeInfos": {
"title": "List"
},
"additionalFields": []
}

  • Entity: Một thực thể đại diện cho một đối tượng.

Ví dụ:

{
"type": "entity",
"value": {},
"marker": "entity",
"position": 15,
"listTitles": [
{
"title": "Sản phẩm",
"value": {
"id": 1,
"depth": 0,
"parentId": null,
"position": 1,
"selected": true
}
},
{
"title": "Trang bình thường",
"value": {
"id": 4,
"depth": 0,
"parentId": null,
"position": 2,
"selected": true
}
},
{
"title": "Lỗi",
"value": {
"id": 2,
"depth": 0,
"parentId": null,
"position": 3,
"selected": true
}
}
],
"validators": {},
"localizeInfos": {
"title": "Entity"
},
"additionalFields": [
{
"type": "string",
"value": "Trường thử nghiệm",
"marker": "test_field"
}
]
}

  • Time interval: Một lịch linh hoạt với giao diện thân thiện cho việc quản lý dữ liệu khoảng thời gian.

Ví dụ:

{
"type": "timeInterval",
"value": {},
"marker": "time_interval",
"position": 16,
"listTitles": [],
"validators": {},
"localizeInfos": {
"title": "Time Interval"
},
"additionalFields": []
}

  • JSON: Một số dữ liệu ở định dạng JSON.

Ví dụ:

{
"type": "json",
"value": {},
"marker": "json",
"position": 17,
"listTitles": [],
"validators": {},
"localizeInfos": {
"title": "Json"
},
"additionalFields": []
}

Giao diện điền nội dung sẽ tương ứng với loại dữ liệu đã chọn cho mỗi trường thuộc tính.


💡 Lưu ý quan trọng

Validators

Bạn có thể thêm các bộ xác thực cho các thuộc tính để đảm bảo chất lượng dữ liệu:

  • Trường bắt buộc
  • Độ dài tối thiểu/tối đa cho văn bản
  • Giới hạn kích thước tệp cho các tệp tải lên
  • Kích thước pixel cho hình ảnh
  • Khoảng thời gian ngày

Tìm hiểu thêm: Xem phần "Validators" để biết cấu hình chi tiết.

Bộ thuộc tính chia sẻ

⚠️ Quan trọng: Nếu một bộ thuộc tính được sử dụng bởi nhiều thực thể, hãy cẩn thận khi thực hiện thay đổi:

Xóa một thuộc tính:

  • ❌ Xóa nó ở mọi nơi bộ được sử dụng
  • ❌ Xóa tất cả nội dung trong trường đó
  • ⚠️ Không thể hoàn tác!

Thêm một thuộc tính:

  • ✅ Thêm ở mọi nơi bộ được sử dụng
  • ✅ Nội dung hiện có không thay đổi
  • ℹ️ Trường mới sẽ trống cho các mục hiện có

Ví dụ:

"Thông tin sản phẩm" được sử dụng bởi:
- Sản phẩm vật lý
- Sản phẩm kỹ thuật số
- Dịch vụ

Xóa thuộc tính "trọng lượng" → Bị xóa khỏi TẤT CẢ ba! ⚠️

📊 Bảng tham khảo nhanh - Các phương thức phổ biến

Phương thứcChức năngKhi nào sử dụng
getAttributes()Lấy tất cả các đối tượng bộ thuộc tính.
getAttributesByMarker()Lấy tất cả các thuộc tính theo marker với dữ liệu từ bộ thuộc tính.
getAttributeSetByMarker()Lấy một đối tượng duy nhất của bộ thuộc tính theo marker.
getSingleAttributeByMarkerSet()Lấy một thuộc tính với dữ liệu từ bộ thuộc tính.

❓ Câu hỏi thường gặp (FAQ)

Sự khác biệt giữa string và text là gì?

  • string - Văn bản ngắn, một dòng (tối đa ~255 ký tự). Sử dụng cho tên, tiêu đề, email.
  • text - Văn bản dài, nhiều đoạn văn, hỗ trợ định dạng và HTML. Sử dụng cho mô tả, bài viết.

Khi nào tôi nên sử dụng integer so với float?

  • integer - Chỉ số nguyên: 1, 2, 100, -5. Sử dụng cho số lượng, đếm, tuổi.
  • float - Số thập phân: 19.99, 4.5, -0.25. Sử dụng cho giá, đánh giá, đo lường.
  • real - Giống float nhưng độ chính xác cao hơn. Sử dụng cho các tính toán khoa học.

Thực hành tốt nhất: Lập kế hoạch cho các loại thuộc tính của bạn trước khi thêm nội dung.


Điều gì xảy ra nếu tôi xóa một thuộc tính?

  • Bạn không thể xóa một thuộc tính nếu nó đang được sử dụng trong một bộ thuộc tính.

Tôi có thể tái sử dụng cùng một thuộc tính trong các bộ thuộc tính khác nhau không?

Không, mỗi thuộc tính thuộc về một bộ thuộc tính. Nhưng bạn có thể:

  • Tạo các thuộc tính tương tự với các marker khác nhau
  • Tái sử dụng toàn bộ bộ thuộc tính trên nhiều thực thể

"Marker" là gì và tại sao nó quan trọng?

Marker là định danh kỹ thuật mà bạn sử dụng trong mã:

// Trong mã của bạn:
product.attributeValues.product_name // ← "product_name" là marker

// So với tên (hiển thị trong quản trị):
"Tên sản phẩm" // ← Đây chỉ dành cho con người

Quy tắc cho markers:

  • Phải duy nhất
  • Không có khoảng trắng (sử dụng _)
  • Không thể bắt đầu bằng số
  • Sử dụng chữ thường
  • Chọn tên mô tả

Làm thế nào tôi biết loại nào để sử dụng cho dữ liệu của mình?

Hãy tự hỏi:

  1. Nó có phải là văn bản không?

    • Ngắn (< 255 ký tự)? → string
    • Dài với định dạng? → text
    • Cần tiêu đề? → textWithHeader
  2. Nó có phải là một số không?

    • Không có số thập phân? → integer
    • Có số thập phân? → float
    • Độ chính xác khoa học? → real
  3. Nó có phải là một lựa chọn không?

    • Chọn một tùy chọn? → radioButton
    • Menu thả xuống? → list
  4. Nó có phải là một tệp không?

    • Hình ảnh? → image hoặc groupOfImages
    • Tài liệu? → file
  5. Nó có phải là một ngày không?

    • Chỉ ngày? → date
    • Ngày + giờ? → dateTime
    • Khoảng thời gian? → timeInterval

Tôi có thể có các thuộc tính lồng nhau (thuộc tính bên trong thuộc tính) không?

Không trực tiếp, nhưng bạn có thể sử dụng:

  • Loại entity để liên kết đến nội dung khác
  • Loại json để lưu trữ dữ liệu có cấu trúc
  • Nhiều bộ thuộc tính để tổ chức các trường liên quan

Làm thế nào tôi thêm quy tắc xác thực?

Trong bảng điều khiển quản trị OneEntry:

  1. Đi đến bộ thuộc tính của bạn
  2. Nhấp vào một thuộc tính
  3. Thêm các bộ xác thực (bắt buộc, min/max, regex, v.v.)
  4. Lưu thay đổi

Các bộ xác thực phổ biến:

  • Trường bắt buộc
  • Độ dài tối thiểu/tối đa
  • Định dạng email
  • Định dạng URL
  • Giới hạn kích thước tệp
  • Kích thước hình ảnh

🎓 Thực hành tốt nhất

  • Sử dụng các marker mô tả (product_price không phải pp)
  • Lập kế hoạch cho các loại thuộc tính trước khi thêm nội dung
  • Tái sử dụng các bộ thuộc tính khi có thể
  • Thêm các bộ xác thực để đảm bảo chất lượng dữ liệu
  • Tài liệu cho biết mỗi thuộc tính dùng để làm gì

Thông tin thêm về giao diện người dùng của mô-đun https://doc.oneentry.cloud/docs/attributes/introduction

Định nghĩa của mô-đun AttributesSets


const { AttributesSets } = defineOneEntry(
"your-project-url", {
"token": "your-app-token"
}
);


🔗 Tài liệu liên quan