Der Entwickler des Inhaltslayouts muss die Struktur der vom Inhaltslayout empfangenen Daten standardisieren.
Wenn alle Daten vorhanden sind, kann das Inhaltslayout die Komponente einfach rendern. Wenn nicht alle Daten vorhanden sind, muss das Inhaltslayout unter Umständen zusätzliche Abfragen senden. In keinem Fall darf das Inhaltslayout von einem bestimmten Datenformat ausgehen. Es muss stattdessen ein renderbares Format für die Daten erzwingen.
Stellen Sie sicher, dass alle erwarteten Daten vorhanden sind. Wenn sie nicht vorhanden sind, müssen Sie die zusätzlichen Abfragen senden. Die folgenden Felder können in den Daten fehlen:
Der "fields
"-Eintrag für referenzierte Felder
Große Textfelder
Da Inhaltslayouts für spezielle Inhaltstypen entworfen werden, weiß der Entwickler eines Inhaltslayouts, welche Felder erforderlich sind. Für jedes dieser Felder müssen die Daten abgerufen werden, damit das Inhaltslayout gerendert werden kann. Ihnen stehen zwei Optionen zur Verfügung: Fehlende Daten abrufen und dann mit vollständigen Daten rendern oder sofort rendern und dann fehlende Daten abrufen, um Lücken zu füllen.
Option 1: Fehlende Daten abrufen und dann mit vollständigen Daten rendern
Erstellen Sie einen Promise, um die erforderlichen Daten abzurufen, und setzen Sie das Rendering dann fort, wenn alle Promises zurückgegeben wurden.
Beispiel mit den folgenden Inhaltstypen und den zugehörigen Feldern:
starter-blog-author
Felder
starter-blog-author_name
- Textfeld
starter-blog-author_bio
- Textfeld
starter-blog-post
Felder
starter-blog-post_title
- Textfeld
starter-blog-post_content
- großes Textfeld
starter-blog-post_author
- Referenz zu einem starter-blog-author
-Element
Das Inhaltslayout verwendet die folgende Vorlage zum Rendern dieser erwarteten Feldwerte:
{{#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}}
Das Inhaltslayout kann mit Daten aus den folgenden Abfragen aufgerufen werden:
Elementabfrage mit "expand
" - alle Daten werden angegeben
/content/published/api/v1.1/items/{id}?expand=fields.starter-blog-post_author&channelToken=8dd714be0096ffaf0f7eb08f4ce5630f
Dieses Datenformat ist erforderlich, um alle Werte in der Vorlage erfolgreich aufzufüllen. Wenn eine der anderen Abfragen verwendet wird, müssen weitere Schritte ausgeführt werden, um die Daten abzurufen und in dieses Format zu konvertieren.
"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": "..." } } }
Elementabfrage ohne "expand
" - referenzierte Elementfelder "starter-blog-post_author.fields" fehlen:
/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-Abfrage - großes Textfeld "starter-blog-post_content" fehlt, referenzierte Elementfelder "starter-blog-post_author.fields" fehlen:
/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 ein konsistentes Rendering mit einer dieser Abfragen muss die Datei render.js
aus dem Inhaltslayout sicherstellen, dass alle referenzierten Felder erweitert und die großen Textfelder vorhanden sind.
Andernfalls muss sie diese Felder erneut abfragen, die Daten korrigieren und dann das Rendering mit vollständigen Daten vornehmen.
render()
-Beispielfunktion:
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); } }); }
Option 2: Sofort rendern und dann fehlende Daten abrufen, um Lücken zu füllen
Sie können die Performance verbessern, indem Sie die eventuell nicht vorhandenen Elemente herausfiltern und in einem zweiten Durchgang rendern. Dazu sind zwei Mustache-Vorlagen erforderlich: Eine für das erste Rendering, bei dem "Lücken" verbleiben, die dann mit dem zweiten Rendering gefüllt werden, wenn die Daten vollständig sind.
Hierzu müssen Sie die Mustache-Vorlage so einrichten, dass sie mehrere Durchläufe unterstützt, entweder indem Sie separate Vorlagen für die "Lüken" verwenden oder festlegen, dass das Modell Vorlagenmakros anstelle tatsächlicher Werte zurückgibt. In jedem Fall müssen Sie diese Lücken "verbergen", bis die Daten abgerufen wurden, und sie anschließend füllen und mit geeigneter UI-Animation anzeigen, um ein übermäßiges "Herumspringen" der Seite zu vermeiden.