Utvecklaren av innehållslayouten måste standardisera datastrukturen som innehållslayouten tar emot.
Om alla data finns med kan innehållslayouten helt enkelt återge komponenten. Om inte alla data finns med kan innehållslayouten behöva utföra ytterligare frågor. Under alla omständigheter ska innehållslayouten aldrig anta ett visst dataformat och i stället tvinga data till ett format som kan återges.
Du måste säkerställa att du har alla data som du förväntar dig. Om data inte finns måste du skapa de ytterligare frågorna. Följande fält kanske saknas i dessa data:
Posten "fields
" för fält som det refereras till
Stora textfält
Eftersom innehållslayouter är utformade för specifika innehållstyper känner utvecklaren av innehållslayouten till listan över de fält som behövs. För vart och ett av dessa fält måste data hämtas så att innehållslayouten kan återges. Du har två alternativ att välja mellan: hämta data som saknas och sedan återge med fullständiga data eller återge omedelbart och sedan hämta data som saknas för att fylla i luckorna.
Alternativ 1: Hämta data som saknas och sedan återge med fullständiga data
Skapa ett löfte om hämtning av de data som krävs och fortsätt sedan med återgivningen när alla löften returneras.
Till exempel kan vi ha följande innehållstyper med motsvarande fält:
starter-blog-author
fält
starter-blog-author_name
– textfält
starter-blog-author_bio
– textfält
starter-blog-post
fält
starter-blog-post_title
– textfält
starter-blog-post_content
– stort textfält
starter-blog-post_author
– referens till objektet starter-blog-author
Innehållslayouten har följande mall för att återge dessa förväntade fältvärden:
{{#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}}
Innehållslayouten kan anropas med data från följande frågor:
Objektsfråga med "expand
" – alla data angivna
/content/published/api/v1.1/items/{id}?expand=fields.starter-blog-post_author&channelToken=8dd714be0096ffaf0f7eb08f4ce5630f
Det här är det dataformat som krävs för att alla värden i mallen ska kunna fyllas i. Om någon av de andra frågorna används krävs ytterligare arbete för att hämta data och konvertera dem till det här 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": "..." } } }
Objektsfråga, utan "expand
" – objektsfälten "starter-blog-post_author.fields" som det refereras till saknas:
/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-fråga – det stora textfältet "starter-blog-post_content" saknas, fälten "starter-blog-post_author.fields" för objekt som det refereras till saknas:
/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" } }
För att kunna återge konsekvent med dessa frågor måste render.js
från innehållslayouten kontrollera att alla fält som det refereras till expanderas och att de stora textfälten finns med.
Om så inte är fallet måste den fråga tillbaka om dessa, åtgärda data och sedan återge med fullständiga data.
Exempel på funktionen 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); } }); }
Alternativ 2: Återge omedelbart och sedan hämta data som saknas för att fylla i luckorna
Prestanda kan förbättras genom att de objekt som kanske inte finns med skiljs ut och återges i en andra omgång. För detta krävs två Mustache-mallar, varav den första gör den första återgivningen, och lämnar "hål" som sedan fylls i med den andra återgivningen när data har blivit fullständiga.
För detta krävs att Mustache-mallen ställs in så att den stöder flera omgångar, antingen genom att ha separata mallar för "hålen" eller genom att låta modellen returnera mallmakron snarare än faktiska värden. I båda fallen måste du "dölja" de här hålen tills data har hämtats och sedan fylla i dem och visa dem med lämplig användargränssnittsanimering för att undvika att sidan "hoppar omkring" alltför mycket.