Standardisere datastrukturen for et innholdsoppsett

Utvikleren av innholdsoppsett må standardisere strukturen for dataene som innholdsoppsettet mottar.

Hvis alle dataene finnes, kan innholdsoppsettet ganske enkelt gjengi komponenten. Hvis alle dataene ikke finnes, må innholdsoppsettet kanskje utføre flere spørringer. I alle tilfeller må innholdsoppsettet aldri anta et bestemt dataformat, og i stedet tvinge dataene til et format som skal gjengis.

Du må forsikre deg om at du får alle dataene du forventer. Hvis dataene ikke finnes, må du utføre flere spørringer. Følgende felt mangler kanskje i dataene:

  • Oppføringen fields for refererte felt

  • Store tekstfelt

Siden innholdsoppsett er utformet for bestemte innholdstyper, kjenner utvikleren av et innholdsoppsett listen over nødvendige felt. For hvert av disse feltene må dataene hentes slik at innholdsoppsettet kan gjengi dem. Du har to valg: hente manglende data og deretter gjengi med fullstendige data, eller gjengi umiddelbart og deretter hente manglende data til å fylle hull.

Valg 1: Hent manglende data og gjengi deretter med fullstendige data

Opprett en lovnad om å hente de nødvendige dataene, og fortsett deretter med å gjengi alle returnerte lovnader.

Vi har for eksempel følgende innholdstyper med tilsvarende felt:

  • starter-blog-author

    • felt

      • starter-blog-author_name - tekstfelt

      • starter-blog-author_bio - tekstfelt

  • starter-blog-post

    • felt

      • starter-blog-post_title - tekstfelt

      • starter-blog-post_content - stort tekstfelt

      • starter-blog-post_author - refererer til et element av typen starter-blog-author

Innholdsoppsettet har følgende mal som gjengir disse forventede feltverdiene:

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

Det kan sendes kall til innholdsoppsettet med data fra følgende spørringer:

  • Elementspørring med expand - alle angitte data

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

    • Dette er formatet for dataene som trengs til å fylle ut alle verdiene i malen. Hvis én av de andre spørringene brukes, trengs det mer arbeid når dataene skal hentes og konverteres til dette formatet.

    • "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": "..."
              }
          }
      }
  • Elementspørring uten expand - mangler de refererte elementfeltene 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-spørring - mangler det store tekstfeltet starter-blog-post_content, mangler de refererte elementfeltene 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"
          }
      }

Hvis du vil gjengi konsistent med hvilke som helst av disse spørringene, må render.js fra innholdsoppsettet forsikre at alle de refererte feltene er utvidet, og at de store tektsfeltene finnes.

Hvis det ikke er tilfellet, må det utføres spørring på nytt, og dataene må rettes og deretter gjengis med fullstendige data.

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

Valg 2: Gjengi umiddelbart og hent deretter manglende data så hull kan fylles

Ytelsen kan forbedres ved å skille ut elementer som kanskje ikke finnes, og gjengi dem i en andre runde. Dette trenger to Mustache-maler. Den første utfører den innledende gjengivelsen, og etterlater huller som deretter fylles med andre gjengivelse så snart dataene er fullstendige.

Dette krever definisjon av Mustache-malene slik at de støtter flere runder, enten ved å ha atskilte maler for hullene, eller ved å få modellen til å returnere malmakroer i stedet for faktiske verdier. I begge tilfeller må du skjule disse hullene inntil dataene blir hentet, og deretter fylle og vise dem med passende UI-animering slik at det unngås at siden hopper for mye.