コンテンツ・レイアウトのデータ構造の標準化
コンテンツ・レイアウト開発者は、コンテンツ・レイアウトが受信するデータの構造を標準化する必要があります。
すべてのデータが存在する場合は、コンテンツ・レイアウトでコンポーネントを単にレンダリングできます。 データの一部が存在しない場合、コンテンツ・レイアウトで問合せを追加する必要がある場合があります。 いずれの場合も、コンテンツ・レイアウトでは特定のデータ・フォーマットが想定されることはなく、レンダリングされるフォーマットにデータが強制的に変換されます。
データがすべて期待どおりであることを確認する必要があります。 データが存在しない場合は、追加の問合せを行う必要があります。 データから次のフィールドが欠落している可能性があります:
-
参照フィールドの
fields
エントリ -
大きいテキスト・フィールド
コンテンツ・レイアウトは特定のコンテンツ・タイプ用に設計されているため、コンテンツ・レイアウトの開発者は必要なフィールドのリストを把握します。 これらの各フィールドについて、コンテンツ・レイアウトがレンダリングできるようにデータをフェッチする必要があります。 2つのオプションがあります: 欠落データをフェッチしてから、完全なデータでレンダリングするか、すぐにレンダリングしてから、空白を埋めて欠落データをフェッチします。
オプション1: 欠落データのフェッチおよび完了データでのレンダリング
約束を作成して必要なデータを取得し、すべての約束が戻ったときにレンダリングを続行します。
たとえば、対応するフィールドがある次のコンテンツ・タイプがあります:
-
starter-blog-author
-
fields
-
starter-blog-author_name
- テキスト・フィールド -
starter-blog-author_bio
- テキスト・フィールド
-
-
-
starter-blog-post
-
fields
-
starter-blog-post_title
- テキスト・フィールド -
starter-blog-post_content
- 大きいテキスト・フィールド -
starter-blog-post_author
-starter-blog-author
アイテムへの参照
-
-
コンテンツ・レイアウトには次のテンプレートがあり、想定されるフィールド値をレンダリングします:
{{#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}}
コンテンツ・レイアウトは、次の問合せからデータを使用してコールできます:
-
expand
を使用したアイテム問合せ - 指定されたすべてのデータ-
/content/published/api/v1.1/items/{id}?expand=fields.starter-blog-post_author&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" "fields": { "starter-blog-author_bio": "...", "starter-blog-author_name": "..." } } }
-
-
アイテム問合せ(
expand
なし) - 参照アイテム・フィールドが" 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問合せ - 大きいテキスト・フィールド"starter-blog-post_content"がありません。参照アイテム・フィールド" 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" } }
-
これらのいずれかの問合せで一貫してレンダリングできるようにするには、コンテンツ・レイアウトからのrender.js
を使用して、参照されるすべてのフィールドが展開され、大きいテキスト・フィールドが存在することを確認する必要があります。
そうでない場合は、これらのバックアップを問い合せてデータを修正し、完全なデータを使用してレンダリングする必要があります。
サンプルの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);
}
});
}
オプション2: 即座にレンダリングした後、欠落しているデータをフェッチしてバケットに入力
パフォーマンスを向上するには、存在しない可能性があるアイテムを分離し、それらを2番目のパスにレンダリングします。 これには2つの大きいテンプレートが必要です。最初のレンダリングを実行するテンプレートは、データが完了してから2番目のレンダリングでいっぱいになる穴のままになります。
これには、穴に個別のテンプレートを使用するか、実際の値ではなくモデル戻りテンプレートのマクロを使用することで、複数のパスをサポートするようにMustacheテンプレートを設定する必要があります。 どちらの場合も、データが取得されるまでこれらの穴を非表示にしてから移入し、適切なUIアニメーションを使用してページの移動移動を回避する必要があります。