Standardisere strukturen af data for et indholdslayout

Udvikleren af indholdslayout skal standardisere strukturen af data, som indholdslayoutet modtager.

Hvis alle data er til stede, kan indholdslayoutet blot gengive komponenten. Hvis alle data ikke er til stede, skal indholdslayoutet muligvis foretage yderligere forespørgsler. Indholdslayoutet må aldrig antage, at der skal bruges et bestemt dataformat, men skal i stedet indsætte data i et format, der kan gengives.

Du skal sikre dig, at du har alle de forventede data. Hvis dataene ikke findes, skal du foretage yderligere forespørgsler. Følgende felter kan mangle i dataene:

  • Posten "fields" for felter, der refereres til

  • Store tekstfelter

Da indholdslayout er designet til specifikke indholdstyper, kender udvikleren af et indholdslayout listen over nødvendige felter. Dataene skal hentes for hvert af disse felter, så indholdslayoutet kan gengives. Du har to valgmuligheder: Du kan hente manglende data og derefter gengive med alle data eller gengive straks og derefter hente manglende data for at udfylde hullerne.

Valgmulighed 1: Hente manglende data og derefter gengive med alle data

Opret et løfte for at hente de påkrævede data og derefter fortsætte med gengivelsen, når alle løfter er returneret.

Vi har for eksempel følgende indholdstyper med tilsvarende felter:

  • starter-blog-author

    • felter

      • starter-blog-author_name - tekstfelt

      • starter-blog-author_bio - tekstfelt

  • starter-blog-post

    • felter

      • starter-blog-post_title - tekstfelt

      • starter-blog-post_content - stort tekstfelt

      • starter-blog-post_author - reference til elementet starter-blog-author

Indholdslayoutet har følgende skabelon til gengivelse af disse forventede feltværdier:

{{#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}}

Indholdslayoutet kan kaldes med data fra følgende forespørgsler:

  • Elementforespørgsel med "expand" - alle data leveres

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

    • Dette er det dataformat, der kræves at opnå en vellykket udfyldelse af alle værdierne i skabelonen. Hvis en af de andre forespørgsler bruges, er det nødvendigt med yderligere arbejde for at hente dataene og konvertere dem til dette 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": "..."
              }
          }
      }
  • Elementforespørgsel uden "expand" - manglende elementfelter, der refereres til "starter-blog-post_author.fields":

    • /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"
          }
      }
  • SCIM-forespørgsel - manglende stort tekstfelt "starter-blog-post_content", manglende elementfelter, der refereres til "starter-blog-post_author.fields":

    • /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"
          }
      }

For at kunne gengive disse forespørgsler konsekvent skal render.js fra indholdslayoutet sørge for, at alle de felter, der refereres til, er udvidet, og de store tekstfelter er til stede.

Hvis det ikke er tilfældet, skal den forespørge bagud, rette dataene og derefter gengive de komplette data.

Eksempel på render()-funktion:

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);
        }    
    });
}

Valgmulighed 2: Gengive straks og derefter hente manglende data for at udfylde hullerne

Ydeevnen kan forbedres, ved at de elementer, der muligvis ikke er til stede, udskilles og gengives i et andet gennemløb. Det kræver to Mustache-skabeloner, hvor den første foretager den indledende gengivelse, der efterlader "huller", som derefter udfyldes i den anden gengivelse, når dataene er komplette.

Det kræver opsætning af Mustache-skabelonen, så den understøtter flere gennemgange, ved enten at have separate skabeloner til "huller" eller få modellen til at returnere skabelonmakroer i stedet for faktiske værdier. I begge tilfælde skal du "skjule" disse huller, indtil dataene hentes, og derefter udfylde og vise dem med passende animation i brugergrænsefladen for at undgå, at siden "hopper for meget omkring".