Padronizar a Estrutura de Dados de um Layout de Conteúdo

O desenvolvedor de layout de conteúdo precisa padronizar a estrutura de dados que o layout de conteúdo recebe.

Se todos os dados estiverem presentes, o layout de conteúdo simplesmente poderá renderizar o componente. Se nem todos os dados estiverem presentes, o layout de conteúdo poderá precisar fazer consultas adicionais. Em todos os casos, o layout de conteúdo nunca deve assumir um determinado formato de dados e, em vez disso, coagir os dados a um formato que será renderizado.

Assegure-se de que você tenha todos os dados que está esperando. Se os dados não existirem, faça as consultas adicionais. Os seguintes campos possivelmente estarão faltando nos dados:

  • A entrada "fields" para campos referenciados

  • Campos de texto grandes

Como os layouts de conteúdo são projetados para tipos de conteúdo específicos, o desenvolvedor de um layout de conteúdo conhece a lista de campos necessários. Para cada um desses campos, os dados precisam ser extraídos para que o layout de conteúdo possa ser renderizado. Você tem duas opções: extrair dados ausentes e depois renderizar com dados completos ou renderizar imediatamente e depois extrair dados ausentes para preencher os brancos.

Opção 1: Extrair Dados Ausentes e depois Renderizar com Dados Completos

Crie uma Promessa para recuperar os dados exigidos e, em seguida, continuar renderizando quando todas as Promessas forem retornadas.

Por exemplo, temos os seguintes tipos de conteúdo com os campos correspondentes:

  • starter-blog-author

    • campos

      • starter-blog-author_name - campo de texto

      • starter-blog-author_bio - campo de texto

  • starter-blog-post

    • campos

      • starter-blog-post_title - campo de texto

      • starter-blog-post_content - campo de texto grande

      • starter-blog-post_author - referência a um item starter-blog-author

O Layout de Conteúdo tem o seguinte modelo para renderizar estes valores de campo esperados:

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

O Layout de Conteúdo pode ser chamado com dados das seguintes consultas:

  • Consulta de item com "expand" - todos os dados fornecidos

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

    • Este é o formato dos dados que são exigidos para preencher com sucesso todos os valores no modelo. Se qualquer uma das outras consulta for utilizada, um trabalho adicional será necessário para extrair os dados e convertê-los nesse formato.

    • "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": "..."
              }
          }
      }
  • Consulta de item, sem "expand" - campos de itens referenciados ausentes "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"
          }
      }
  • Consulta de SCIM - campo de texto grande ausente "starter-blog-post_content", campos de itens referenciados ausentes "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"
          }
      }

Para poder renderizar de forma consistente com qualquer uma dessas consultas, o arquivo render.js do layout de conteúdo precisa se certificar de que todos os campos referenciados sejam expandidos e que campos de texto grande estejam presentes.

Se esse não for o caso, ele precisará tornar a consultá-los, corrigir os dados e depois renderizar com os dados completos.

Função render() de amostra:

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

Opção 2: Renderizar Imediatamente e depois Extrair Dados Ausentes para Preencher os Brancos

O desempenho pode ser melhorado separando os itens que possam não estar presentes e renderizando-os em uma segunda fase. Isso exigirá dois modelos Mustache, o primeiro para fazer a renderização inicial, deixando "furos" que depois são preenchidos com a segunda renderização após a conclusão dos dados.

Isso exige a configuração do modelo Mustache para suportar diversas fases, tendo modelos distintos para os "furos" ou fazer o exemplar retornar macros de modelo em vez de valores reais. Em qualquer dos dois casos, você precisará "esconder" esses furos até que os dados sejam recuperados e depois preenchê-los e mostrá-los com a animação apropriada da interface do usuário para evitar muitos "pulos" de página.