Edge Delivery Services ブロックの開発

IMPORTANT
AEM Edge Functionsは現在ベータ版です。 機能やドキュメントは変更される可能性があります。 フィードバックについては、aemcs-edgecompute-feedback@adobe.comまでお問い合わせください。

目標は、AEM Edge関数を呼び出してサードパーティ APIから動的データを取得する動的なEdge Delivery Services ブロックを​ ビルド ​することです。

2つ目のステップは、JSON モデル、JavaScript、CSSを作成し、ユニバーサルエディターで作成するEdge Delivery Services ブロックを作成することです。 ブロックモデルの構文とJavaScriptおよびCSS構造の基本については、​ ブロックの作成および​ ブロックの作成を参照してください。 ここでは、このチュートリアルに固有の部分のみを説明します。

この手順では、前の手順で構築したAEM Edge関数はまだ呼び出されません。 Edge Delivery Services ブロックは、​ ブロックをAEM Edge関数に接続してフェッチを接続するまで、プレースホルダー結果をレンダリングします。

ブランチを作成

Edge Delivery Services サイトプロジェクトで、この機能のブランチを作成します。

$ git checkout -b estimated-delivery

ブロックモデルの定義

JavaScriptを記述する前に、作成者が制御するフィールドと、コードが独自にレンダリングするフィールドを定義します。これにより、コンテンツモデルは小さく保たれます。

_estimated-delivery.jsonのモデルでは、見出しとボタンのラベルの2つのフィールドのみが表示されます。 商品リスト、フォームマークアップ、および結果の状態は、作成済みコンテンツではなく、Edge Delivery Services ブロックのJavaScriptによってレンダリングされます。

// blocks/estimated-delivery/_estimated-delivery.json
{
  "definitions": [
    {
      "title": "Estimated Delivery",
      "id": "estimated-delivery",
      "plugins": {
        "xwalk": {
          "page": {
            "resourceType": "core/franklin/components/block/v1/block",
            "template": {
              "name": "Estimated Delivery",
              "model": "estimated-delivery",
              "title": "When will it arrive?",
              "ctaText": "Check estimated delivery"
            }
          }
        }
      }
    }
  ],
  "models": [
    {
      "id": "estimated-delivery",
      "fields": [
        {
          "component": "text",
          "valueType": "string",
          "name": "title",
          "value": "When will it arrive?",
          "label": "Heading",
          "description": "Main heading shown above the delivery checker form."
        },
        {
          "component": "text",
          "valueType": "string",
          "name": "ctaText",
          "value": "Check estimated delivery",
          "label": "CTA Text",
          "description": "Label for the submit button."
        }
      ]
    }
  ],
  "filters": []
}

textを超えるフィールドタイプの場合は、​ ブロックを作成のモデル構文に従います。

ユニバーサルエディター用ブロックの登録

ユニバーサルエディターがインサートピッカーでブロックを提供するには、ブロックモデルファイルだけでは不十分です。 さらに2つのファイルが自動的に検出されるのではなく、名前でブロックをリストするため、最初に手動エントリが必要です。

ブロックをmodels/_component-definition.jsonの「ブロック」グループに追加します。

{ "...": "../blocks/estimated-delivery/_*.json#/definitions" }

ブロックをセクション内に挿入できる場合は、そのIDをmodels/_section.jsonfilters[0].componentsにも追加します。

"estimated-delivery"

models/_component-models.jsonにはこの処理は必要ありません。 ワイルドカード ../blocks/*/_*.json#/modelsを通じてすべてのブロックが自動的に含まれるため、ブロックのフィールドスキーマだけでもcomponent-models.jsonに到達するのに十分です。 models/_component-definition.jsonmodels/_section.jsonはこのプロジェクトにワイルドカードを使用していないため、新しいブロックは、モデルが正しくコンパイルされたとしても、名前で両方に追加されるまでピッカーに表示されません。

両方の編集内容をプロジェクトの集計ファイル (component-definition.jsoncomponent-filters.jsonおよびcomponent-models.json)にコンパイルします(​ プロジェクト JSONの構築に関する記事を参照)。

ブロックを実装する

追加するファイル

blocks/estimated-delivery/
├── _estimated-delivery.json   # the block model, shown above
├── estimated-delivery.js      # decorate() renders the form and result states
└── estimated-delivery.css     # form layout and result state styling

フォームとプレースホルダー結果のレンダリング

製品選択、ポストコード入力、送信ボタン、空の結果領域をレンダリングするdecorate()関数を作成します。 今のところ、送信ハンドラーをスタブとして保持します。

readBlockContent()は、ブロックのDOMから2つの作成済みフィールドを読み取ります。 ユニバーサルエディターは、各モデルフィールドをフィールドの順序で子<div>としてレンダリングするので、見出しは最初の子のテキストで、ボタンラベルは2番目の子のテキストで、フィールドが空の場合はデフォルトにフォールバックします。

// blocks/estimated-delivery/estimated-delivery.js
const DEFAULTS = {
  title: 'When will it arrive?',
  ctaText: 'Check estimated delivery',
};

const PRODUCTS = [
  { value: 'house-blend-medium-roast', label: 'House Blend - Medium Roast' },
  { value: 'frescopa-smart-machine', label: 'Fréscopa Smart Machine' },
  { value: 'insulated-travel-thermos', label: 'Insulated Travel Thermos' },
];

const PRODUCT_OPTIONS_HTML = PRODUCTS.map(
  (p) => `<option value="${p.value}">${p.label}</option>`,
).join('');

function getBlockText(el, fallback) {
  const text = el?.textContent?.trim();
  return text || fallback;
}

function readBlockContent(block) {
  const props = [...block.children].map((row) => row.firstElementChild);

  return {
    title: getBlockText(props[0], DEFAULTS.title),
    ctaText: getBlockText(props[1], DEFAULTS.ctaText),
  };
}

export default function decorate(block) {
  const { title, ctaText } = readBlockContent(block);

  block.innerHTML = `
    <div class="estimated-delivery">
      <h3 data-aue-prop="title" data-aue-label="Heading" data-aue-type="text">${title}</h3>
      <form class="estimated-delivery__form">
        <select name="sku">${PRODUCT_OPTIONS_HTML}</select>
        <input name="postcode" type="text" placeholder="e.g. 10001" required />
        <button type="submit" data-aue-prop="ctaText" data-aue-label="CTA Text" data-aue-type="text">${ctaText}</button>
      </form>
      <div class="estimated-delivery__result" aria-live="polite">
        <p>Select a product, enter your postcode, and click the button.</p>
      </div>
    </div>
  `;

  // form submit logic added in the next step
}

data-aue-propdata-aue-labelおよびdata-aue-typeは、見出しとボタンのテキストをユニバーサルエディターで編集可能なフィールドとしてマークします。これは、​ ブロックの作成で使用されているのと同じパターンです。 これは最終版ファイルではなく基礎モードです。 参照実装のestimated-delivery.jsには、​ ブロックをAEM Edge関数に接続するからのフェッチ ロジックも含まれており、そのロジックが配置されると完全なファイルにリンクされます。

NOTE
一部のブロックの基礎フィールドは、readBlockConfigscripts/aem.jsからインポートするテンプレートから開始します。 このブロックは使っていません。 2つのフィールドのみを使用すると、readBlockContent()を使用して位置を読み取ることは、キー値の設定形式readBlockConfigが期待するよりも簡単です。 エディタがインポートを追加した場合は、そのインポートを削除します。

ブロックのスタイル設定

フォームレイアウトにCSSを追加し、プレースホルダーの状態を確認します。その結果、Edge Delivery Services ブロックは後でレンダリングされます(読み込み、エラー、成功)。CSSとJavaScriptを使用してブロックを作成します。 estimated-delivery.cssからの代表抜粋:

/* blocks/estimated-delivery/estimated-delivery.css */
.estimated-delivery__form {
  display: grid;
  gap: var(--spacing-small);
  padding: var(--spacing-medium);
  background: #fff;
  border-radius: 12px;
  box-shadow: 0 4px 12px rgb(0 0 0 / 6%);
}

.estimated-delivery__placeholder {
  display: grid;
  gap: var(--spacing-xsmall);
  align-content: center;
  border: 2px dashed var(--color-neutral-400);
  border-radius: 12px;
  text-align: center;
}

ファイル全体では、読み込みスピナーとサクセスカードのステータスカラー(in-stocklow-stockout-of-stock)もスタイル設定されます。Edge Delivery Services ブロックはAEM Edge関数にブロックを接続するまでレンダリングされません。

コードをプッシュしてブロックを作成する

  1. ブランチをGitHubにプッシュします。

  2. AEM オーサー環境にログインします。 AEMの開始ページから、ツール > Cloud Services > Edge Delivery Services Configuration​に移動します。

    Edge Delivery Services設定リスト ​

  3. サイト (Frescopa)、次に{Org}/{Repo} エントリ、次に​ プロパティ ​を選択して、Edge Delivery サービス構成​を開きます。 Branch フィールドをestimated-deliveryに更新し、保存して閉じる​を選択します。

    Edge Delivery Service Configuration ブランチ フィールド ​

  4. AEM Sitesで、このブランチのページ構造(例:/content/frescopa/en/dev/branches/estimated-delivery)を、​ ブロックの作成と同じ​ブランチ ページパターンに従って作成します。

    推定配信ブランチのAEM Sites ページ構造

  5. ユニバーサルエディターでページを開き、推定配信 ブロックをページに追加し、見出しとボタンのテキストを作成します。

    ​ ユニバーサルエディターで作成された推定配信ブロック ​

  6. プレビューに公開して、コンテンツをローカル開発サーバーで使用できるようにします。

ブロックをローカルでプレビューする

Edge Delivery Services サイトをローカルで実行し、フェッチ呼び出しを接続する前にプレースホルダーレンダリングを確認します。

$ aem up

http://localhost:3000/dev/branches/estimated-deliveryで作成したページを開き、作成した見出し、フォーム、プレースホルダーテキストのレンダリングを確認します。 送信ボタンはまだ何も実行しません。

​ ローカル開発サーバーの推定配信ブロック プレースホルダー

次の手順

​ ブロックをAEM Edge Functionに接続すると、このEdge Delivery Services ブロックは前の手順で構築したAEM Edge Functionにワイヤー接続され、プレースホルダーの結果がライブデータに置き換えられます。

その他のリソース

recommendation-more-help
experience-manager-learn-help-cloud-service