Introduction
Définissez des champs personnalisés pour votre contenu sans toucher au code.
🎯 Que fait ce module ?
Le module AttributesSets vous permet d'utiliser des champs personnalisés pour votre contenu (produits, pages, formulaires, etc.) sans les coder en dur dans votre application.
Considérez-le comme un constructeur de formulaires pour vos données - vous définissez les champs dont vous avez besoin, et OneEntry s'occupe du reste.
📖 Explication Simple
Imaginez que vous construisez une boutique en ligne. Chaque produit a besoin de :
- Nom (texte).
- Prix (nombre).
- Image (photo).
- Description (texte long).
- Catégorie (liste déroulante).
Au lieu de coder ces champs en dur dans votre application, vous utilisez Attributes pour les définir dans le panneau d'administration de OneEntry. Ensuite, vous pouvez :
- Ajouter de nouveaux champs à tout moment (sans modifications de code !).
- Réutiliser des champs à travers différents types de contenu.
- Changer les types de champs sans redéploiement.
- Gérer toute la structure de contenu en un seul endroit.
Exemple du monde réel :
Without Attributes (hardcoded):
- Code: const product = { name: 'Product name', price: 150, image: '', description: '' }
- To add "color" field → Change code, redeploy, wait.
With Attributes (dynamic):
- Code: const { name, price, image, description } = product
- Admin panel: Add "color" attribute.
- Code automatically includes new field.
- Code: const { name, price, image, description, color } = product
- No deployment needed!
✨ Concepts Clés
Qu'est-ce qu'un Attribut ?
Un attribut est un champ unique qui stocke des données.
Exemples :
- Nom du produit (chaîne).
- Prix du produit (flottant).
- Image du produit (image).
- Date de publication (date).
Qu'est-ce qu'un Ensemble d'Attributs ?
Un ensemble d'attributs est une collection d'attributs qui définissent une structure.
Exemple : Ensemble d'Attributs de Produit
- name (string)
- price (float)
- description (text)
- images (group of images)
- category (list)
- inStock (integer)
Pourquoi Utiliser des Ensembles d'Attributs ?
| ❌ Sans Attributs | ✅ Avec Attributs |
|---|---|
| Champs codés en dur | Champs dynamiques |
| Modifications de code nécessaires | Éditez dans le panneau d'administration |
| Redéploiement requis | Mises à jour en direct |
| Structure rigide | Structure flexible |
| Code dupliqué | Ensembles réutilisables |
📋 Ce Que Vous Devez Savoir
Trois Termes Importants
| Terme | Ce Que C'est | Exemple |
|---|---|---|
| Marqueur | Identifiant de code unique | "product_name" |
| Type | Quel type de données il stocke | "string", "integer", "image" |
| Valeur | Valeur de l'attribut | "Nom du Produit" |
Important concernant les Marqueurs :
- Doit être unique
- Pas d'espaces autorisés (utilisez
_à la place) - Ne peut pas commencer par un chiffre
- Utilisez des minuscules pour la cohérence
Exemples :
- ✅ Bon :
product_name,price_usd,main_image - ❌ Mauvais :
product name,2nd_price,Product Name
📚 Types de Données Disponibles
Les attributs peuvent stocker différents types de données. Choisissez le bon type pour chaque champ.
Tableau de Référence Rapide
| Type | Meilleur Pour | Utilisation Exemple |
|---|---|---|
| string | Texte court | Nom du produit, email |
| text | Texte long formaté | Article de blog, description |
| textWithHeader | Texte avec titre | Sections d'articles |
| integer | Nombres entiers | Quantité, âge |
| real | Décimales de haute précision | Données scientifiques |
| float | Nombres décimaux | Prix, évaluation |
| date | Juste la date | Date de naissance, date limite |
| dateTime | Date + heure | Début d'événement, publié à |
| time | Juste l'heure | Heures d'ouverture |
| file | Tout fichier | PDF, document |
| image | Image unique | Avatar, logo |
| groupOfImages | Plusieurs images | Galerie photo |
| radioButton | Choix unique | Taille (S/M/L) |
| list | Sélection déroulante | Pays, catégorie |
| entity | Lien vers d'autres contenus | Produits associés |
| timeInterval | Plage de dates | Période de promotion |
| json | Données structurées personnalisées | Réponse API |
🔍 Descriptions Détaillées des Types de Données
Types de Texte
Quand utiliser quoi :
- string - Ligne unique, moins de 255 caractères (nom, email, titre)
- text - Plusieurs paragraphes, prend en charge le formatage (articles, descriptions)
- textWithHeader - Texte nécessitant un titre (sections de blog, FAQ)
Types de Nombres
Quand utiliser quoi :
- integer - Pas de décimales nécessaires (âge, quantité, vues)
- float - Décimales standard (prix 19,99 $, évaluation 4,5)
- real - Précision supplémentaire nécessaire (calculs scientifiques)
Types de Date/Heure
Quand utiliser quoi :
- date - Juste le jour (anniversaire, date limite)
- time - Juste l'heure (heures d'ouverture, heure de rendez-vous)
- dateTime - Les deux nécessaires (début d'événement, article publié)
- timeInterval - Période entre les dates (durée de vente, dates de vacances)
Types de Fichiers et d'Images
Quand utiliser quoi :
- file - Tout document (PDF, DOC, ZIP)
- image - Une image (photo de produit, avatar)
- groupOfImages - Plusieurs images (galerie, images de produit)
Types de Sélection
Quand utiliser quoi :
- radioButton - Choisissez UNE seule option (Oui/Non, Taille S/M/L)
- list - Menu déroulant avec options (Pays, Catégorie, Statut)
Types Avancés
- entity - Lien vers d'autres pages/produits (Articles Associés, Catégories)
- json - Stocker des structures de données complexes (réponses API, paramètres)
📖 Exemples de Types de Données
Voici des exemples techniques de la structure de chaque type de données.
💡 Les données retournées dans l'ensemble d'attributs n'incluent pas les valeurs d'attribut réelles, car ces valeurs sont contenues dans des entités spécifiques telles que des pages, des produits, etc. La seule exception est le type d'attribut timeInterval. Cet attribut peut avoir des valeurs en cochant la case correspondante dans le panneau d'administration
Cliquez pour voir tous les exemples de types de données
Référence des Types de Données
Les types de données peuvent être des types suivants :
- String : Texte simple, par exemple, "Bonjour, le monde !".
Exemple :
{
"type": "string",
"value": {},
"marker": "string",
"position": 1,
"listTitles": [],
"validators": {
"requiredValidator": {
"strict": true
}
},
"localizeInfos": {
"title": "String"
},
"additionalFields": [
{
"type": "integer",
"value": "10",
"marker": "Extra"
}
]
}
- Text : Texte plus long, souvent formaté, par exemple, un article ou une lettre.
Exemple :
{
"type": "text",
"value": {},
"marker": "text",
"position": 2,
"listTitles": [],
"validators": {},
"localizeInfos": {
"title": "Text"
},
"additionalFields": []
}
- Text with Header : Texte avec un en-tête qui peut être utilisé pour désigner un sujet ou une catégorie.
Exemple :
{
"type": "textWithHeader",
"value": {},
"marker": "text_with_header",
"position": 3,
"listTitles": [],
"validators": {},
"localizeInfos": {
"title": "Text With Header"
},
"additionalFields": []
}
- Integer : Un entier, par exemple, 5, 100, -2.
Exemple :
{
"type": "integer",
"value": {},
"marker": "integer",
"position": 4,
"listTitles": [],
"validators": {},
"localizeInfos": {
"title": "Integer"
},
"additionalFields": []
}
- Real : Identique à Float, mais avec une précision plus élevée.
Exemple :
{
"type": "real",
"value": {},
"marker": "real_number",
"position": 5,
"listTitles": [],
"validators": {},
"localizeInfos": {
"title": "Real Number"
},
"additionalFields": []
}
- Float : Un type de données pour les nombres à virgule flottante qui peuvent avoir une partie décimale, par exemple, 3,14, 1,5, -0,25.
Exemple :
{
"type": "float",
"value": {},
"marker": "float",
"position": 6,
"listTitles": [],
"validators": {},
"localizeInfos": {
"title": "Float"
},
"additionalFields": []
}
- Date and Time : Une combinaison de date et d'heure, par exemple, 2023-10-27 10:00:00.
Exemple :
{
"type": "dateTime",
"value": {},
"marker": "date_time",
"position": 7,
"listTitles": [],
"validators": {},
"localizeInfos": {
"title": "DateTime"
},
"additionalFields": []
}
- Date : Une date, par exemple, 2023-10-27.
Exemple :
{
"type": "date",
"value": {},
"marker": "date",
"position": 8,
"listTitles": [],
"validators": {},
"localizeInfos": {
"title": "Date"
},
"additionalFields": []
}
- Time : Une heure, par exemple, 10:00:00.
Exemple :
{
"type": "date",
"value": {},
"marker": "date",
"position": 8,
"listTitles": [],
"validators": {},
"localizeInfos": {
"title": "Date"
},
"additionalFields": []
}
- File : Tout fichier sur votre ordinateur, par exemple, un document, une image, de la musique.
Exemple :
{
"type": "file",
"value": {},
"marker": "file",
"position": 10,
"listTitles": [],
"validators": {
"checkingFilesValidator": {
"maxUnits": "kb",
"maxValue": "2000",
"minUnits": "kb",
"minValue": 0,
"extensions": []
}
},
"localizeInfos": {
"title": "File"
},
"additionalFields": []
}
- Image : Une image, par exemple, une photographie, un dessin.
Exemple :
{
"type": "image",
"value": {},
"marker": "image",
"position": 11,
"listTitles": [],
"validators": {
"sizeInPixelsValidator": {
"maxX": "500",
"maxY": "500"
}
},
"localizeInfos": {
"title": "Image"
},
"additionalFields": []
}
- Group of Images : Une collection d'images, par exemple, un album photo.
Exemple :
{
"type": "groupOfImages",
"value": {},
"marker": "image_group",
"position": 12,
"listTitles": [],
"validators": {},
"localizeInfos": {
"title": "Image Group"
},
"additionalFields": []
}
- Radio Button : Un bouton de sélection à partir duquel une seule option peut être choisie.
Exemple :
{
"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 : Une liste d'articles, par exemple, une liste de courses.
Exemple :
{
"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 : Une entité représentant un objet.
Exemple :
{
"type": "entity",
"value": {},
"marker": "entity",
"position": 15,
"listTitles": [
{
"title": "Products",
"value": {
"id": 1,
"depth": 0,
"parentId": null,
"position": 1,
"selected": true
}
},
{
"title": "Normal Page",
"value": {
"id": 4,
"depth": 0,
"parentId": null,
"position": 2,
"selected": true
}
},
{
"title": "Error",
"value": {
"id": 2,
"depth": 0,
"parentId": null,
"position": 3,
"selected": true
}
}
],
"validators": {},
"localizeInfos": {
"title": "Entity"
},
"additionalFields": [
{
"type": "string",
"value": "Test Field",
"marker": "test_field"
}
]
}
- Time interval : Un calendrier flexible avec une interface conviviale pour gérer les données d'intervalle de temps.
Exemple :
{
"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": {
"en_US": {
"title": "Time interval"
}
},
"receiveValues": true
}
}
- JSON : Certaines données au format JSON.
Exemple :
{
"type": "json",
"value": {},
"marker": "json",
"position": 17,
"listTitles": [],
"validators": {},
"localizeInfos": {
"title": "Json"
},
"additionalFields": []
}
L'interface de remplissage de contenu correspondra au type de données sélectionné pour chaque champ d'attribut.
💡 Notes Importantes
Validateurs
Vous pouvez ajouter des validateurs pour les attributs afin d'assurer la qualité des données :
- Champs obligatoires.
- Longueur min/max pour le texte.
- Limites de taille de fichier pour les téléchargements.
- Dimensions en pixels pour les images.
- Plages de dates.
Cliquez pour voir des exemples de validateurs
- requiredValidator : Nécessite qu'une valeur soit saisie.
Exemple :
{
"type": "string",
"value": {},
"marker": "string",
"position": 1,
"listTitles": [],
"validators": {
"requiredValidator": {
"strict": true
}
},
"localizeInfos": {
"title": "Currency"
},
"additionalFields": [
{
"type": "integer",
"value": "10",
"marker": "extra"
}
]
}
- defaultValueValidator :
Exemple :
{
"type": "string",
"value": {},
"marker": "string",
"position": 1,
"listTitles": [],
"validators": {
"defaultValueValidator": {
"customErrorText": "Custom error",
"fieldDefaultValue": "usd",
"fieldDefaultValue2": "",
},
},
"localizeInfos": {
"title": "String"
},
"additionalFields": [
{
"type": "integer",
"value": "10",
"marker": "extra"
}
]
}
En savoir plus : Consultez la section Validateurs pour une configuration détaillée.
Ensembles d'Attributs Partagés
⚠️ Important : Si un ensemble d'attributs est utilisé par plusieurs entités, soyez prudent lors des modifications :
Ajout d'un attribut :
- Il sera ajouté à toutes les entités qui utilisent l'ensemble.
- Le contenu existant reste inchangé.
- Le nouveau champ sera vide pour les éléments existants.
Suppression d'un attribut :
- Il sera supprimé de toutes les entités qui utilisent l'ensemble.
- Les valeurs existantes seront définitivement supprimées.
Exemple :
"Product Info" attribute set used by:
- Physical Products
- Digital Products
- Services
Adding "weight" attribute → Added to ALL three!
Removing "weight" attribute → Removed from ALL three! ⚠️
📊 Tableau de Référence Rapide - Méthodes Courantes
| Méthode | Ce Qu'elle Fait |
|---|---|
| getAttributes() | Récupérer tous les objets d'ensembles d'attributs. |
| getAttributesByMarker() | Récupérer tous les attributs par marqueur avec des données de l'ensemble d'attributs. |
| getAttributeSetByMarker() | Récupérer un objet unique d'ensemble d'attributs par marqueur. |
| getSingleAttributeByMarkerSet() | Récupérer un attribut avec des données de l'ensemble d'attributs. |
❓ Questions Fréquemment Posées (FAQ)
Quelle est la différence entre string et text ?
- string - Texte court, ligne unique (max ~255 caractères). Utilisez pour les noms, titres, emails.
- text - Texte long, plusieurs paragraphes, prend en charge le formatage et HTML. Utilisez pour les descriptions, articles.
Quand devrais-je utiliser integer vs float ?
- integer - Nombres entiers uniquement :
1, 2, 100, -5. Utilisez pour les quantités, les comptes, les âges. - float - Nombres décimaux :
19.99, 4.5, -0.25. Utilisez pour les prix, les évaluations, les mesures. - real - Comme float mais avec une précision plus élevée. Utilisez pour les calculs scientifiques.
Meilleure pratique : Planifiez vos types d'attributs avant d'ajouter du contenu.
Que se passe-t-il si je supprime un attribut ?
- Vous ne pouvez pas supprimer un attribut s'il est utilisé dans un ensemble d'attributs.
Puis-je réutiliser le même attribut dans différents ensembles d'attributs ?
Non, chaque attribut appartient à un seul ensemble d'attributs. Mais vous pouvez :
- Créer des attributs similaires avec des marqueurs différents
- Réutiliser des ensembles d'attributs entiers à travers plusieurs entités
Qu'est-ce que le "marqueur" et pourquoi est-il important ?
Le marqueur est l'identifiant technique que vous utilisez dans le code :
// In your code:
product.attributeValues.product_name // ← "product_name" is the marker
// VS the name (shown in admin):
"Product Name" // ← This is just for humans
Règles pour les marqueurs :
- Doit être unique
- Pas d'espaces (utilisez
_) - Ne peut pas commencer par des chiffres
- Utilisez des minuscules
- Choisissez des noms descriptifs
Comment savoir quel type utiliser pour mes données ?
Demandez-vous :
-
Est-ce du texte ?
- Court (< 255 caractères) ? →
string - Long avec formatage ? →
text - Nécessite un titre ? →
textWithHeader
- Court (< 255 caractères) ? →
-
Est-ce un nombre ?
- Pas de décimales ? →
integer - A des décimales ? →
float - Précision scientifique ? →
real
- Pas de décimales ? →
-
Est-ce un choix ?
- Choisissez une option ? →
radioButton - Menu déroulant ? →
list
- Choisissez une option ? →
-
Est-ce un fichier ?
- Image ? →
imageougroupOfImages - Document ? →
file
- Image ? →
-
Est-ce une date ?
- Juste la date ? →
date - Date + heure ? →
dateTime - Période ? →
timeInterval
- Juste la date ? →
Puis-je avoir des attributs imbriqués (attributs à l'intérieur d'attributs) ?
Oui, vous pouvez utiliser Champs Supplémentaires
Comment ajouter des règles de validation ?
Dans le panneau d'administration de OneEntry :
- Allez à votre ensemble d'attributs
- Cliquez sur un attribut
- Ajoutez des validateurs (obligatoire, min/max, regex, etc.)
- Enregistrez les modifications
En savoir plus : Consultez la section Validateurs pour une configuration détaillée.
🎓 Meilleures Pratiques
- Utilisez des marqueurs descriptifs (
product_pricepaspp) - Planifiez les types d'attributs avant d'ajouter du contenu
- Réutilisez les ensembles d'attributs lorsque cela est possible
- Ajoutez des validateurs pour garantir la qualité des données
- Documentez l'utilisation de chaque attribut
Plus d'informations sur l'interface utilisateur du module https://doc.oneentry.cloud/docs/attributes/introduction
Définition du module AttributesSets
const { AttributesSets } = defineOneEntry( "your-project-url", { "token": "your-app-token" });
🔗 Documentation Connexe
- Module Produits - Utilise des ensembles d'attributs pour les données produit
- Module Pages - Utilise des ensembles d'attributs pour le contenu des pages
- Module Blocs - Utilise des ensembles d'attributs pour des blocs réutilisables
- Module Formulaires - Créez des formulaires avec des champs personnalisés