Normalisation de la structure des données de présentation de contenu

Le développeur de présentation de contenu doit normaliser la structure des données que la présentation de contenu reçoit.

Si toutes les données sont présentes, la présentation de contenu peut tout simplement afficher le composant. S'il manque des données, la présentation de contenu peut avoir besoin d'effectuer des requêtes supplémentaires. Dans tous les cas, la présentation de contenu ne doit jamais utiliser un certain format de données, elle doit plutôt contraindre les données dans un format permettant l'affichage.

Vous devez veiller à disposer de toutes les données attendues. Si les données n'existent pas, vous devez effectuer des requêtes supplémentaires. Il est possible que les champs suivants soient manquants dans les données :

  • Entrée "fields" des champs référencés

  • Champs de texte long

Etant donné que les présentations de contenu sont conçues pour des types spécifiques de contenu, le développeur d'une présentation de contenu connaît la liste des champs nécessaires. Pour chacun de ces champs, les données doivent être extraites pour que la présentation de contenu puisse être affichée. Vous disposez de deux options : extraire les données manquantes et afficher ensuite le contenu avec les données complètes ou afficher immédiatement le contenu et extraire ensuite les données manquantes pour remplir les blancs.

Option 1 : extraire les données manquantes et afficher ensuite le contenu avec les données complètes

Créez une promesse pour extraire les données requises et poursuivre l'affichage lorsque toutes les promesses sont renvoyées.

Prenons par exemple les types de contenu suivants et les champs correspondants :

  • starter-blog-author

    • Champs

      • starter-blog-author_name : champ de texte

      • starter-blog-author_bio : champ de texte

  • starter-blog-post

    • Champs

      • starter-blog-post_title : champ de texte

      • starter-blog-post_content : champ de texte long

      • starter-blog-post_author : référence à un élément starter-blog-author

La présentation de contenu possède le modèle suivant pour afficher ces valeurs de champ attendues :

{{#fields}}
<div class="blog_container">
    <div class="blog-post-title">{{starter-blog-post_title}}</div>
    {{#starter-blog-post_author.fields}}
    <div class="blog-author-container">
        <div class="blog-author-details">
            <div class="blog-author-name">{{starter-blog-author_name}}</div>
            <div class="blog-author-bio">{{{starter-blog-author_bio}}}</div>
            <span class="more-from-author">More articles from this author</span>
        </div>
    </div>
    {{/starter-blog-post_author.fields}}
    <div class="blog-post-content">{{{starter-blog-post_content}}}</div>
</div>
{{/fields}}

La présentation de contenu peut être appelée avec les données des requêtes suivantes :

  • Requête d'élément avec "expand" : toutes les données fournies

    • /content/published/api/v1.1/items/{id}?expand=fields.starter-blog-post_author&channelToken=8dd714be0096ffaf0f7eb08f4ce5630f

    • Ce format de données est requis pour remplir correctement toutes les valeurs du modèle. Si les autres requêtes sont employées, un travail supplémentaire est nécessaire pour extraire les données et les convertir dans ce format.

    • "fields": {    
          "starter-blog-post_title": "...",
          "starter-blog-post_summary": "...",
          "starter-blog-post_content": "...",
          "starter-blog-post_author": {
              "id": "CORE386C8733274240D0AB477C62271C2A02",
              "type": "Starter-Blog-Author"
              "fields": {
                  "starter-blog-author_bio": "...",
                  "starter-blog-author_name": "..."
              }
          }
      }
  • Requête d'élément, sans "expand" : champs d'élément référencés "starter-blog-post_author.fields" manquants :

    • /content/published/api/v1.1/items/{id}?channelToken=8dd714be0096ffaf0f7eb08f4ce5630f
    • "fields": {    
          "starter-blog-post_title": "...",
          "starter-blog-post_summary": "...",
          "starter-blog-post_content": "...",
          "starter-blog-post_author": {
              "id": "CORE386C8733274240D0AB477C62271C2A02",
              "type": "Starter-Blog-Author"
          }
      }
  • Requête SCIM : champ de texte long "starter-blog-post_content" manquant, champs d'élément référencés "starter-blog-post_author.fields" manquants :

    • /content/published/api/v1.1/items?q=(type eq "Starter-Blog-Post")&fields=ALL&channelToken=8dd714be0096ffaf0f7eb08f4ce5630f

    • "fields": {
          "starter-blog-post_title": "...",
          "starter-blog-post_summary": "...",
          "starter-blog-post_author": {
              "id": "CORE386C8733274240D0AB477C62271C2A02",
              "type": "Starter-Blog-Author"
          }
      }

Pour pouvoir obtenir un affichage cohérent avec ces requêtes, le fichier render.js de la présentation de contenu doit garantir que tous les champs référencés sont développés et que les champs de texte long sont présents.

Si ce n'est pas le cas, il doit réexécuter les requêtes, corriger les données, puis exécuter l'affichage avec les données complètes.

Exemple de fonction render() :

render: function (parentObj) {
    var self = this,
        template,
        contentClient = self.contentClient,
        content = self.contentItemData;

     var getRefItems = function (contentClient, ids) {
        // Calling getItems() with no "ids" returns all items.
        // If no items are requested, just return a resolved Promise.
        if (ids.length === 0) {
            return Promise.resolve({});
        } else {
            return contentClient.getItems({
                "ids": ids
            }); 
        }
     };
   
     var fetchIDs = [], // list of items to fetch
         referedFields = ['starter-blog-post_author'], // names of reference fields
         largeTextFields = ['starter-blog-post_content'], // large text fields in this asset
         fieldsData = content.fields;
     // See if we need to fetch any referenced fields
     referedFields.forEach(function (fieldName) {
         if(fieldsData[fieldName] && fieldsData[fieldName].fields) {
            // got data already, nothing else to do
         } else { 
             // fetch this item
             fetchIDs.push(fieldsData[fieldName].id);
         }
     });

     // See if we need to fetch any large text fields
     for(var i = 0; i < largeTextFields.length; i++) {
        if(!fieldsData[largeTextFields[i]]) {
           // need to fetch this content item directly to get all the large text fields
            fetchIDs.push(content.id);
            break;
        }
     }
    // now we have the IDs of all the content items we need to fetch, get them all before continuing
    getRefItems(contentClient, fetchIDs).then(function (referenceData) {
        var items = referenceData && referenceData.items || [];

        // add the data back in
        items.forEach(function (referencedItem){
            // check if it's the current item
            if(referencedItem.id === content.id) {
               // copy across the large text fields 
               largeTextFields.forEach(function (fieldName) {
                   fieldsData[fieldName] = referencedItem.fields[fieldName];
                });
            } else{
                // check for any referenced fields
                for (var i = 0; i < referedFields.length; i++) {
                    if(referencedItem.id === fieldsData[referedFields[i]].id){
                       // copy across the fields values
                       fieldsData[referedFields[i]].fields = referencedItem.fields;
                       break;
                    }
                }
            }
        });

        // now data is fixed up, we can continue as before
        try{
           // Mustache
           template = Mustache.render(templateHtml, content);

             if(template) {
                $(parentObj).append(template);
             }

        } catch (e) {            
            console.error(e.stack);
        }    
    });
}

Option 2 : afficher immédiatement le contenu et extraire ensuite les données manquantes pour remplir les blancs

Les performances peuvent être améliorées si les éléments éventuellement non présents sont séparés et affichés lors d'une deuxième transmission. Pour ce faire, vous avez besoin de deux modèles Mustache, le premier pour l'affichage initial, laissant des "vides", et le second pour l'affichage suivant qui remplit les vides une fois que les données sont complètes.

Vous devez donc configurer le modèle Mustache de sorte qu'il prenne en charge plusieurs transmissions. Pour ce faire, configurez des modèles séparés pour les "vides" ou configurez le modèle pour qu'il renvoie des macros plutôt que des valeurs réelles. Dans les deux cas, vous devez "masquer" ces vides jusqu'à ce que les données soient extraites, puis les remplir et les afficher avec l'animation appropriée d'interface utilisateur pour éviter que la page ne "saute" trop.