O programador da disposição de conteúdo deve normalizar a estrutura dos dados recebidos pela disposição de conteúdo.
Se todos os dados estiverem presentes, a disposição de conteúdo pode simplesmente renderizar o componente. Se nem todos os dados estiverem presentes, a disposição de conteúdo poderá necessitar de efetuar consultas adicionais. Em todos os casos, a disposição de conteúdo nunca deve assumir um determinado formato de dados e, em vez disso, deve coagir os dados para um formato que seja renderizado.
Deverá certificar-se de que tem todos os dados esperados. Se os dados não existirem, será necessário efetuar consultas adicionais. Os campos seguintes poderão estar em falta nos dados:
A entrada "fields" para campos referenciados
Campos de texto grande
Como as disposições de conteúdo são concebidas para tipos de conteúdo específicos, o programador de uma disposição de conteúdo está a par da lista de campos necessários. Para cada um destes campos, é necessário extrair os dados para que a disposição de conteúdo possa ser renderizada. Tem duas opções: extrair os dados em falta e, em seguida, renderizar com os dados completos ou renderizar imediatamente e, em seguida, extrair os dados em falta para preencher os campos.
Opção 1: Extrair Dados em Falta e Depois Renderizar com Dados Completos
Crie um Promise para obter os dados necessários e depois continuar a renderizar quando todos os Promises forem devolvidos.
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
A Disposição de Conteúdo tem o seguinte modelo, para renderizar estes valores de campos 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}}
A Disposição de Conteúdo pode ser chamada com os 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 necessários para preencher com êxito todos os valores no modelo. Se alguma das outras consultas for utilizada, é necessário trabalho adicional para extrair os dados e convertê-los para este 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 "starter-blog-post_author.fields" de itens referenciados em falta:
/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 "starter-blog-post_content" de texto grande em falta, campos "starter-blog-post_author.fields" de itens referenciados em falta:
/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 renderizar de modo consistente com qualquer uma destas consultas, o render.js da disposição de conteúdo deve assegurar que todos os campos referenciados são expandidos e que os campos de texto grande estão presentes.
Se não for este o caso, é necessário voltar a consultar, corrigir os dados e, em seguida, renderizar com os dados completos.
Função render() de exemplo:
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 os Dados em Falta para Preencher os Campos
É possível melhorar o desempenho ao separar os itens que poderão não estar presentes e renderizá-los num segundo passo. Para isso, são necessários dois modelos Mustache, o primeiro para efetuar a renderização inicial, deixando "espaços" que serão depois preenchidos na segunda renderização, quando os dados estiverem completos.
Isto requer que o modelo Mustache seja configurado para suportar várias transmissões ao ter modelos separados para os "espaços" ou ao fazer com que o modelo devolva macros do modelo, em vez dos valores reais. Em qualquer um dos casos, deverá "ocultar" estes espaços até os dados serem obtidos e, em seguida, preenchê-los e mostrá-los com animação da IU adequada, para evitar que a página pareça "saltar" demasiado.