Chuyển đến nội dung chính

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ã.

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


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

Mô-đun AttributesSets cho phép bạn đọc các định nghĩa trường tùy chỉnh (tập hợp thuộc tính) được sử dụng bởi nội dung của bạn - sản phẩm, trang, biểu mẫu, khối và nhiều hơn nữa. Một tập hợp thuộc tính là sơ đồ mô tả các trường mà một thực thể có và loại của từng trường; bạn định nghĩa chúng trong bảng điều khiển quản trị OneEntry và lấy cấu trúc của chúng bằng mô-đun này.

Lưu ý: các tập hợp thuộc tính mô tả sơ đồ, không phải giá trị. Các giá trị thực tế sống trên chính các thực thể (một trang, sản phẩm, v.v.) dưới attributeValues của chúng. Một ngoại lệ duy nhất là loại timeInterval, có thể mang giá trị - xem các ví dụ bên dưới.

🚀 Bắt đầu nhanh

Khởi tạo mô-đun từ defineOneEntry:


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

Lấy các thuộc tính được định nghĩa trong một tập hợp và đọc các dấu hiệu và loại của chúng:

// Get every attribute in the "productAttributes" set.
const attributes = await AttributesSets.getAttributesByMarker(
"productAttributes",
"en_US",
);

attributes.forEach((attr) => {
console.log(attr.marker, attr.type, attr.localizeInfos.title);
});

✨ Khái niệm chính

Thuộc tính, Tập hợp thuộc tính, Giá trị

Thuật ngữĐịnh nghĩaVí dụ
Thuộc tínhĐịnh nghĩa một trường đơn lẻ (một dấu hiệu + một loại)price (float)
Tập hợp thuộc tínhMột tập hợp các thuộc tính - sơ đồ của thực thểTập hợp "Sản phẩm"
Giá trịDữ liệu mà một thực thể lưu trữ cho một thuộc tính19.99 trên một sản phẩm cụ thể

Một tập hợp thuộc tính nhóm các thuộc tính thành một sơ đồ có thể tái sử dụng. Tập hợp giống nhau có thể được gán cho nhiều thực thể, vì vậy việc thay đổi tập hợp sẽ thay đổi các trường có sẵn ở mọi nơi nó được sử dụng.

Dấu hiệu

Dấu hiệu là định danh kỹ thuật bạn sử dụng trong mã (ví dụ: product_name). Nó ánh xạ đến tiêu đề có thể đọc được của con người hiển thị trong bảng điều khiển quản trị.

product.attributeValues.product_name; // "product_name" is the marker

Quy tắc dấu hiệu:

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

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

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

Tập hợp thuộc tính chia sẻ

Nếu một tập hợp thuộc tính được sử dụng bởi nhiều thực thể, các thay đổi sẽ lan truyền đến tất cả chúng:

  • Thêm một thuộc tính - nó xuất hiện trên mọi thực thể sử dụng tập hợp; nội dung hiện có giữ giá trị của nó và trường mới bắt đầu trống.
  • Xóa một thuộc tính - nó sẽ bị xóa khỏi mọi thực thể sử dụng tập hợp, và các giá trị hiện có sẽ bị xóa vĩnh viễn.

Bạn không thể xóa một thuộc tính trong khi nó vẫn đang được sử dụng trong một tập hợp thuộc tính.

Bộ xác thực

Các thuộc tính có thể mang các bộ xác thực để đảm bảo chất lượng dữ liệu - các trường bắt buộc, độ dài tối thiểu/tối đa, giới hạn kích thước tệp, kích thước pixel hình ảnh, khoảng thời gian, và một giá trị mặc định. Cấu hình bộ xác thực được trả về trên mỗi thuộc tính dưới validators.

Nhấp để xem ví dụ về bộ xác thực
  • requiredValidator: yêu cầu một giá trị phải được nhập.
{
"type": "string",
"value": {},
"marker": "string",
"position": 1,
"listTitles": [],
"validators": {
"requiredValidator": {
"strict": true
}
},
"localizeInfos": {
"title": "Currency"
},
"additionalFields": {
"extra": {
"type": "integer",
"value": "10",
"marker": "extra"
}
}
}

  • defaultValueValidator: cung cấp một giá trị mặc định cho trường.
{
"type": "string",
"value": {},
"marker": "string",
"position": 1,
"listTitles": [],
"validators": {
"defaultValueValidator": {
"customErrorText": "Custom error",
"fieldDefaultValue": "usd",
"fieldDefaultValue2": ""
}
},
"localizeInfos": {
"title": "String"
},
"additionalFields": {
"extra": {
"type": "integer",
"value": "10",
"marker": "extra"
}
}
}

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

Các thuộc tính lồng nhau

Bạn có thể gán các trường bổ sung cho một thuộc tính thông qua Additional Fields (được trả về dưới additionalFields).


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

Phương thứcChức năng
getAttributes()Lấy tất cả các đối tượng tập hợp thuộc tính.
getAttributesByMarker()Lấy tất cả các thuộc tính của một tập hợp, với dữ liệu từ tập hợp thuộc tính.
getAttributeSetByMarker()Lấy một đối tượng tập hợp thuộc tính đơn lẻ theo dấu hiệu.
getSingleAttributeByMarkerSet()Lấy một thuộc tính (với dữ liệu tập hợp) theo dấu hiệu tập hợp và dấu hiệu thuộc tính.

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

Mỗi thuộc tính có một type. Chọn loại phù hợp cho mỗi trường.

LoạiTốt nhất choVí dụ sử dụng
stringVăn bản ngắn (< 255 ký tự)Tê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 bắt đầu sự kiện, ngày xuất bản
timeChỉ giờGiờ mở cửa
fileBất kỳ tệp nàoPDF, tài liệu
imageHình ảnh đơn lẻẢnh đại diện, logo
groupOfImagesNhiều hình ảnhBộ sưu tập ảnh
radioButtonLựa chọn đơnKích thước (S/M/L)
listLựa chọn từ danh sáchQuốc gia, danh mục
buttonHành động tương tácGửi biểu mẫu, CTA
spamBảo vệ chống spam biểu mẫuTrường honeypot chống bot
entityLiên kết đến nội dung khácSản phẩm liên quan
timeIntervalKhoảng thời gianLịch trình, thời gian khuyến mãi

Chọn loại

  • Văn bản: string (dòng đơn), text (đoạn văn định dạng), textWithHeader (văn bản có tiêu đề).
  • Số: integer (không có số thập phân), float (số thập phân tiêu chuẩn), real (độ chính xác cao hơn).
  • Ngày/giờ: date, time, dateTime, hoặc timeInterval (khoảng thời gian/lịch trình).
  • Tệp/hình ảnh: file (bất kỳ tài liệu nào), image (một bức tranh), groupOfImages (một bộ sưu tập).
  • Lựa chọn: radioButton (chọn một), list (danh sách thả xuống).
  • Nâng cao: entity (liên kết đến các trang/sản phẩm khác), button (hành động tương tác), spam (bảo vệ bot).

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

Dưới đây là các ví dụ kỹ thuật về cấu trúc của mỗi loại dữ liệu như được trả về bởi API.

💡 Dữ liệu trả về trong tập hợp thuộc tính không bao gồm các giá trị thuộc tính thực tế - những giá trị đó sống trên các thực thể cụ thể (trang, sản phẩm, v.v.). Ngoại lệ duy nhất là timeInterval, có thể mang giá trị khi ô tương ứng được chọn trong bảng điều khiển quản trị.

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

Tham chiếu các loại dữ liệu

  • String: Văn bản đơn giản, ví dụ, "Xin chào, thế giới!".
{
"type": "string",
"value": {},
"marker": "string",
"position": 1,
"listTitles": [],
"validators": {
"requiredValidator": {
"strict": true
}
},
"localizeInfos": {
"title": "String"
},
"additionalFields": {
"Extra": {
"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ư.
{
"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.
{
"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.
{
"type": "integer",
"value": {},
"marker": "integer",
"position": 4,
"listTitles": [],
"validators": {},
"localizeInfos": {
"title": "Integer"
},
"additionalFields": {}
}

  • Real: Giống như Float, nhưng có độ chính xác cao hơn.
{
"type": "real",
"value": {},
"marker": "real_number",
"position": 5,
"listTitles": [],
"validators": {},
"localizeInfos": {
"title": "Real Number"
},
"additionalFields": {}
}

  • Float: Một số thực có thể có phần thập phân, ví dụ, 3.14, 1.5, -0.25.
{
"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.
{
"type": "dateTime",
"value": {},
"marker": "date_time",
"position": 7,
"listTitles": [],
"validators": {},
"localizeInfos": {
"title": "DateTime"
},
"additionalFields": {}
}

  • Date: Một ngày, ví dụ, 2023-10-27.
{
"type": "date",
"value": {},
"marker": "date",
"position": 8,
"listTitles": [],
"validators": {},
"localizeInfos": {
"title": "Date"
},
"additionalFields": {}
}

  • Time: Một giờ, ví dụ, 10:00:00.
{
"type": "time",
"value": {},
"marker": "time",
"position": 9,
"listTitles": [],
"validators": {},
"localizeInfos": {
"title": "Time"
},
"additionalFields": {}
}

  • File: Bất kỳ tệp nào, ví dụ, một tài liệu, hình ảnh, âm nhạc.
{
"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 hoặc một bức tranh.
{
"type": "image",
"value": {},
"marker": "image",
"position": 11,
"listTitles": [],
"validators": {
"sizeInPixelsValidator": {
"maxX": "500",
"maxY": "500"
}
},
"localizeInfos": {
"title": "Image"
},
"additionalFields": {}
}

  • Group of Images: Một bộ sưu tập hình ảnh, ví dụ, một album ảnh.
{
"type": "groupOfImages",
"value": {},
"marker": "image_group",
"position": 12,
"listTitles": [],
"validators": {},
"localizeInfos": {
"title": "Image Group"
},
"additionalFields": {}
}

  • Radio Button: Một lựa chọn mà chỉ có một tùy chọn có thể được chọn.
{
"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 có thể chọn, ví dụ, một danh sách thả xuống.
{
"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": "Additional Value"
},
"position": 3
}
],
"validators": {},
"localizeInfos": {
"title": "List"
},
"additionalFields": {}
}

  • Entity: Một liên kết đến một đối tượng khác (trang, sản phẩm, …).
{
"type": "entity",
"value": {},
"marker": "entity",
"position": 15,
"listTitles": [
{
"title": "Products",
"value": {
"id": 1,
"depth": 0,
"parentId": null,
"isPinned": false,
"position": 1,
"selected": true
}
},
{
"title": "Normal Page",
"value": {
"id": 4,
"depth": 0,
"parentId": null,
"isPinned": false,
"position": 2,
"selected": true
}
},
{
"title": "Error",
"value": {
"id": 2,
"depth": 0,
"parentId": null,
"isPinned": false,
"position": 3,
"selected": true
}
}
],
"validators": {},
"localizeInfos": {
"title": "Entity"
},
"additionalFields": {
"test_field": {
"type": "string",
"value": "Test Field",
"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.
{
"time_interval": {
"id": 4,
"type": "timeInterval",
"value": [
// Array of value groups, each linked to a specific interval (via intervalId). This array is formed when Receive values is enabled in CMS
{
// Specific time records applicable to the specified dates
"values": [
{
// Unique record identifier
"id": "1dc1787d-acc3-4315-a45d-52166c72e577",
// Date range (inclusive) to which this record applies
"dates": ["2025-11-27T00:00:00.000Z", "2025-11-27T00:00:00.000Z"],
// Array of time slots in format [[start, end], ...]
"times": [
[
// Start of time slot (hours and minutes)
{
"hours": 19,
"minutes": 18
},
// End of time slot
{
"hours": 21,
"minutes": 19
}
]
],
// Reserved (not used in current implementation)
"intervals": [],
// Exceptions — time segments excluded from the schedule on the specified date
"exceptions": [
{
// Exception date
"date": "2025-12-17T17:00:00.000Z",
// Array of excluded time segments
"externalTimes": [
["2025-12-17T17:25:00.000Z", "2025-12-17T17:27:00.000Z"]
]
}
],
// Reference to interval from the `intervals` array
"intervalId": "0da61a19-49cb-40b1-88e6-1fa3c93a1fa6",
// Flag for weekly recurrence (on the corresponding day of the week)
"inEveryWeek": true
},
{
"id": "cfa187d3-0284-4e0d-8206-7b353cf47110",
"dates": ["2025-12-18T00:00:00.000Z", "2025-12-18T00:00:00.000Z"],
// Array of time slots in format [[start, end], ...]
"times": [
[
{
"hours": 0,
"minutes": 25
},
{
"hours": 0,
"minutes": 27
}
],
[
{
"hours": 19,
"minutes": 18
},
{
"hours": 21,
"minutes": 19
}
]
],
"intervals": [],
"exceptions": [
{
"date": "2025-12-17T17:00:00.000Z",
"externalTimes": [
["2025-12-17T17:25:00.000Z", "2025-12-17T17:27:00.000Z"]
]
}
],
"intervalId": "0da61a19-49cb-40b1-88e6-1fa3c93a1fa6"
},
{
"id": "474de0f7-595f-49a5-aaa7-65617203ae69",
"dates": ["2025-12-25T00:00:00.000Z", "2025-12-25T00:00:00.000Z"],
// No time slots
"times": [],
// Dynamic rules for schedule expansion
"external": [
{
// Base date for calculating recurring event
"date": "2026-01-15T00:00:00.000Z",
// Event repeats every month on this day
"inEveryMonth": true
}
],
"intervals": [],
"exceptions": [
{
"date": "2025-12-17T17:00:00.000Z",
"externalTimes": [
["2025-12-17T17:25:00.000Z", "2025-12-17T17:27:00.000Z"]
]
}
],
"intervalId": "0da61a19-49cb-40b1-88e6-1fa3c93a1fa6",
// Flag for weekly recurrence
"inEveryWeek": true,
// Flag for monthly recurrence
"inEveryMonth": true,
// Flag for yearly recurrence
"inEveryYears": true
}
],
// Reference to interval from the `intervals` array
"intervalId": "0da61a19-49cb-40b1-88e6-1fa3c93a1fa6"
},
{
"values": [
{
"id": "2f80dc18-16da-45cb-82c6-e41e1f6ee084",
"dates": ["2025-12-22T00:00:00.000Z", "2025-12-23T00:00:00.000Z"],
"times": [],
"intervals": [],
"exceptions": [],
"intervalId": "918175fd-cc18-4ca5-9bee-c78c61c9415a",
"inEveryWeek": true,
"inEveryMonth": true
}
],
"intervalId": "918175fd-cc18-4ca5-9bee-c78c61c9415a"
}
],
"isPrice": false,
"original": true,
"intervals": [
// Array of time interval templates
{
// Unique identifier of interval template
"id": "0da61a19-49cb-40b1-88e6-1fa3c93a1fa6",
"range": [
// Main range of interval applicability
"2025-11-26T17:00:00.000Z",
"2025-11-26T17:00:00.000Z"
],
// Exceptions at the entire interval level
"external": [
{
"date": "2025-12-17T17:00:00.000Z",
"externalTimes": [
["2025-12-17T17:25:00.000Z", "2025-12-17T17:27:00.000Z"]
]
}
],
// Internal time slots (working/active periods)
"intervals": [
{
"id": "01fea594-9933-47ac-af0a-ec0e0884f618",
// End of time slot
"end": {
"hours": 21,
"minutes": 19
},
// Start of time slot
"start": {
"hours": 19,
"minutes": 18
},
// Duration of repeating block (in minutes); null — no periodicity
"period": null
},
{
"id": "22ba24af-1fae-4422-8c92-0635b684a306",
"end": {
"hours": 0,
"minutes": 29
},
"start": {
"hours": 0,
"minutes": 25
},
// Periodicity: time slots repeat with 2-minute step
"period": 2,
// Exception inside periodic slot
"external": {
// Flag for displaying exception in the interface
"show": false,
// Duration of excluded fragment (in minutes)
"value": 2
}
}
],
"inEveryWeek": true,
"inEveryMonth": true,
"inEveryYears": true
},
{
"id": "918175fd-cc18-4ca5-9bee-c78c61c9415a",
"range": ["2026-01-18T17:00:00.000Z", "2026-01-20T17:00:00.000Z"],
// No exceptions
"external": [],
// No internal time slots
"intervals": [],
"inEveryWeek": true,
"inEveryMonth": true,
"inEveryYears": true
}
],
// Flag for attribute visibility in the interface
"isVisible": true,
"identifier": "time_interval",
"localizeInfos": {
"title": "Time interval"
},
"receiveValues": true
}
}

Giao diện điền nội dung trong bảng điều khiển quản trị tương ứng với loại dữ liệu đã chọn cho mỗi trường 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, 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, float hoặc real?

  • 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). Sử dụng cho giá cả, đánh giá, đo lường.
  • real - giống như float nhưng có độ chính xác cao hơn. Sử dụng cho các phép tính khoa học.

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

Các thuộc tính được định nghĩa trong sơ đồ của một tập hợp thuộc tính (theo dấu hiệu). Để tái sử dụng một trường ở nơi khác, bạn có thể tạo các thuộc tính tương tự với các dấu hiệu khác nhau, hoặc tái sử dụng toàn bộ tập hợp thuộc tính trên nhiều thực thể.


"Dấu hiệu" là gì và tại sao nó quan trọng?

Dấu hiệu là định danh kỹ thuật bạn sử dụng trong mã (ví dụ: product.attributeValues.product_name), trái ngược với tiêu đề có thể đọc được của con người hiển thị trong bảng điều khiển quản trị. Các dấu hiệu phải duy nhất, không chứa khoảng trắng (sử dụng _), không bắt đầu bằng một số, và thường là chữ thường.


Tôi có thể có các thuộc tính lồng nhau không?

Có - sử dụng Additional Fields (được trả về dưới additionalFields).


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: mở tập hợp thuộc tính của bạn, nhấp vào một thuộc tính, thêm các bộ xác thực (bắt buộc, tối thiểu/tối đa, v.v.), và lưu. Tìm hiểu thêm: Validators.


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

  • Sử dụng các dấu hiệu mô tả (product_price, không phải pp).
  • Lập kế hoạch các loại thuộc tính trước khi thêm nội dung.
  • Tái sử dụng các tập hợp thuộc tính trên các thực thể khi có thể.
  • Thêm các bộ xác thực để đảm bảo chất lượng dữ liệu.
  • Nhớ rằng các tập hợp chia sẻ sẽ lan truyền các thay đổi đến mọi thực thể sử dụng chúng.

🔗 Tài liệu liên quan

  • Mô-đun Sản phẩm - Sử dụng các tập hợp thuộc tính cho dữ liệu sản phẩm
  • Mô-đun Trang - Sử dụng các tập hợp thuộc tính cho nội dung trang
  • Mô-đun Khối - Sử dụng các tập hợp thuộc tính cho các khối có thể tái sử dụng
  • Mô-đun Biểu mẫu - Tạo biểu mẫu với các trường tùy chỉnh