JSS Angularアプリでのプレースホルダーの操作

Version:
日本語翻訳に関する免責事項

このページの翻訳はAIによって自動的に行われました。可能な限り正確な翻訳を心掛けていますが、原文と異なる表現や解釈が含まれる場合があります。正確で公式な情報については、必ず英語の原文をご参照ください。

プレースホルダーは、Sitecore JSSで構築されたアプリケーションに不可欠なコンポーネントです。例を示すために、このトピックではSitecore JSS Angularサンプル アプリケーションを使用します。

JSS Angularサンプル・アプリケーションには、ルート・プレースホルダーが付属しています。ルートプレースホルダはsrc/app/routing/layout/layout.component.htmlで定義されています。

sc-placeholderコンポーネントは、AngularのSitecore JSSからインポートされます (@sitecorelabs/sitecore-jss-angular)。

<sc-placeholder name="jss-main" [rendering]="route" (loaded)="onPlaceholderLoaded($event)"></sc-placeholder><sc-placeholder name="jss-main" [rendering]="route"></sc-placeholder>

sc-placeholder Angularコンポーネントには、値jss-mainname属性があり、jss-mainという名前のSitecoreプレースホルダーを表していることを示しています。プレースホルダは、プレースホルダコンポーネントのrendering入力にバインドされたデータで示されるように、ルートデータに基づいて1つ以上のコンポーネントをレンダリングします。

<sc-placeholder name="jss-main" [rendering]="route" (loaded)="onPlaceholderLoaded($event)"></sc-placeholder>
メモ

既存のDOM要素に属性としてsc-placeholderを適用できます。

ルートデータの発信元を理解する

プレースホルダーコンポーネントがrouteデータをどのように受け取るかを理解するには、さまざまなコンポーネント、アプリケーションモジュール、およびサービスがどのように連携するかを理解する必要があります。

本番環境では、JSS Angularアプリケーションをビルドするためのスクリプトは、ユニバーサルレンダリングをサポートするためのサーバーバンドルとクライアントバンドルをビルドします。スクリプトjss buildを実行すると、バンドルは次の場所にあります。

  • Client bundle - dist/browser/にあります。

  • Server bundle - dist/server.bundle.jsにあります。

2つのバンドルを独立して実行することはできません。これらはサーバーによって提供されなければなりません。JSSには、サーバーバンドルを実行できるNode用のJavaScriptビューエンジンが付属しています。JSS JavaScriptビュー エンジンは、renderView関数をエクスポートするserver bundleを想定しています。

2つのバンドルをビルドして提供するために、JSS Angularアプリは、関連するアプリ モジュールとデータ サービスを使用して、アプリケーションの2つのエントリ ポイントを定義します。

このファイルsrc/main.server.tsは、サーババンドルのエントリポイントを定義し、src/app/app.server.module.tsで定義されているサーバAppServerModuleのアプリケーションモジュールをブートストラップします。AppServerModuleは、src/app/jss-context.server-side.service.tsで定義されているJssContextServerSideServiceを使用します。この は、サーバー上で実行され、JSSアプリのコンテキストデータを格納します。コンテキスト データには、現在のルートとSitecoreコンテキスト データのデータが含まれます。

このファイルsrc/main.tsは、クライアント バンドルのエントリ ポイントを定義し、src/app/app.module.tsで定義されているクライアント レンダリングAppModuleのアプリケーション モジュールをブートストラップします。このAppModuleは、src/app/jss-context.service.tsで定義されているJssContextServiceを使用します。このIPアドレスは、クライアント上 (ブラウザー内) で実行され、JSSアプリのコンテキストデータを格納します。

アプリケーションがサーバーバンドルからブラウザーで実行されると、サーバーはAppServerModuleをレンダリングするrenderView関数を呼び出し、JSSアプリのコンテキストデータを準備します。実装の詳細については、ファイルserver.bundle.tsおよび関連サービスを参照してください。どちらのコンテキストサービスもAngular TransferStateクラスを使用します。このクラスは、データを正規化した後、サーバー側のアプリケーション・モジュールからクライアント側のアプリケーション・モジュールに転送されるキー値ストアです。

    renderModule(AppServerModule, {
      document: template,
      url: path,
      extraProviders: [
        // custom injection with the initial state that SSR should utilize
        { provide: 'JSS_SERVER_LAYOUT_DATA', useValue: transferState },
        { provide: 'JSS_SERVER_VIEWBAG', useValue: state.viewBag },
      ],
    })
      .then((html) => callback(null, { html }))
      .catch((err) => callback(err, null));

クライアント側のAppModuleは、src/app/app.component.tsで定義されているルートアプリケーションコンポーネントAppComponentをブートストラップし、src/app/routing/routing.module.tsファイルで定義されているRoutingModuleクラスをインポートします。RoutingModuleは、Angularルーターをアプリケーションルートに接続し、JSS AngularアプリがAngularルーターアウトレットを使用できるようにする役割を担います。

このRoutingModuleは、ルーターのアウトレットプレースホルダーにレンダリングされるコンポーネントを定義します。このコンポーネントは、src/app/routing/layout/layout.component.tsファイルで定義されているLayoutComponentです。RoutingModuleは、ルートを解決するときにアクティブ ルートの状態を設定するJssRouteResolverプロバイダーを使用します。

最後に、routeデータとレイアウトデータの両方が挿入されたLayoutComponentは、アクティブルートをサブスクライブし、Sitecoreコンテキストからルートデータを抽出できます。

この時点で、プレースホルダーコンポーネントは、本番環境の設定でルートのHTMLマークアップをレンダリングできます。

切断モードで作業している場合、JSSアプリケーションはローカルに定義されたファイルから経路データを取得します。サンプル アプリケーションには、src/dataフォルダーに定義済みのローカル データが含まれています。ルート (ホーム ページなど) を読み込むとき、アプリケーションはsrc/data/en.ymlファイルからデータを取得します。レスポンスには、ルートのJSONデータが含まれます。

{
  "context": {
    "pageEditing": false,
    "site": {
      "name": "JssDisconnectedLayoutService"
    },
    "pageState": "normal",
    "language": "en"
  },
  "route": {
    "databaseName": "available-in-connected-mode",
    "deviceId": "available-in-connected-mode",
    "itemId": "home-page",
    "itemLanguage": "en",
    "itemVersion": 1,
    "layoutId": "available-in-connected-mode",
    "templateId": "available-in-connected-mode",
    "templateName": "available-in-connected-mode",
    "name": "home",
    "fields": {
      "pageTitle": {
        "value": "Welcome to Sitecore JSS"
      }
    },
    "placeholders": {
      "jss-main": [
        {
          "uid": "{2C4A53CC-9DA8-5F51-9D79-6EE2FC671B2D}",
          "componentName": "ContentBlock",
          "dataSource": "available-in-connected-mode",
          "params": {},
          "fields": {
            "heading": {
              "value": "Welcome to Sitecore JSS"
            },
            "content": {
              "value": "<p>Thanks for using JSS. Here are some resources to get you started:</p>"
            }
          }
        }
      ]
    }
  }}

routeプロパティのJSONデータ構造には、placeholdersのリストが含まれています。各プレースホルダー名は、コンポーネントの配列に関連付けられています。コンポーネントとプレースホルダのマッピングをcomponent placement rulesと呼びます。

sc-placeholderコンポーネントはrouteプロパティ内のplaceholdersオブジェクトにアクセスできるため、一致するプレースホルダを名前 (jss-main) で検索し、その中のコンポーネントの配列をレンダリングします。この例では、ContentBlockComponentコンポーネントである通常のAngularコンポーネントを動的にレンダリングし、依存関係挿入トークンを通じてheadingフィールドとcontentフィールドを提供します。

import { Component, Input } from '@angular/core';
import { ComponentRendering } from '@sitecore-jss/sitecore-jss-angular';
@Component({
  selector: 'app-content-block',
  templateUrl: './content-block.component.html',
})
export class ContentBlockComponent {
  @Input() rendering: ComponentRendering;
}

renderingプロパティには、データから取得されるContentBlockComponentコンポーネントに関するすべての情報が含まれます。

"componentName": "ContentBlock",
    "dataSource": "available-in-connected-mode",
    "params": {},
    "fields": {
        "heading": {
            "value": "Welcome to Sitecore JSS"
        },
    "content": {
        "value": "<p>Thanks for using JSS. Here are some resources to get you started:</p>"
    }
}

プレースホルダーとコンポーネントのネスト

構成部品には独自のsc-placeholder構成部品を含めることができるため、構成部品配置規則のplaceholdersを使用してその内容を定義できます。

たとえば、WelcomeComponentコンポーネントには次のものが含まれる場合があります。

@Component({
  selector: 'app-welcome',
  template: `
    <sc-placeholder name="welcome" [rendering]="rendering"></sc-placeholder>
  `
})
export class WelcomeComponent {
  rendering: any;
}

この場合、コンポーネント配置ルールで子コンポーネントを定義します。

{
  componentName: 'Welcome',
    fields: {
      title: {
        value: 'Sitecore Experience Platform + JSS',
      },
      text: {
        value: '<p>...</p>',
      },
      logoImage: {
        value: {
          src: '/assets/img/sc_logo.png',
          alt: 'Logo'
        },
      },
    },
    placeholders: {
      welcome: [
        {
          componentName: 'AnotherComponent',
          fields: {
            /* etc */
          }
        }
      ]
    }
}

入力と出力のバインディング

コンポーネントのカスタム・プロパティーは、sc-placeholderinputsおよびoutputsバインディング・プロパティーを使用して、コンポーネントにバインドできます。これらのプロパティを使用すると、プレースホルダー内のすべてのコンポーネントのプロパティへの入力と出力のバインドが可能になります。

これにより、子コンポーネントがsc-placeholderによって動的に作成される場合でも、子コンポーネントとのオーケストレーション/インタラクションが可能になり、複雑なユーザーフローで特に役立ちます。これらのコンポーネントでは、Sitecore XPを通じて管理/最適化する必要があります。

次に、inputsoutputsの簡単な使用例を示します。

@Component({
  selector: 'my-container-component',
  template: `<sc-placeholder
                name="placeholder"
                [rendering]="rendering"
                [inputs]="inputs"
                [outputs]="outputs"
                ></sc-placeholder>`
})
class MyContainerComponent {
  @Input() public rendering: any;

  inputs = {
    hello: 'world',
    something: () => 'can be really complex'
  };
  outputs = {
    onSomething: (type) => alert(type)
  }
}

@Component({selector: 'my-rendering')
class MyRendering {
  // standard on any placeholder-managed component
  @Input() public rendering: any;

  // additional properties for input/output binding
  @Input() hello: string;
  @Input() something: Function;
  @Output() onSomething = new EventEmitter<string>();
}

遅延読み込みプレースホルダー

Sitecoreコンポーネントを遅延読み込みすると、プレースホルダーはデフォルトで空で表示されます。コンポーネントのロード中に表示されるコンポーネントの一時的な本文を指定できます。コンポーネントの読み込みが完了すると、一時的な本体が実際の内容に置き換えられます。次に、簡略化した例を示します。

  <sc-placeholder [rendering]="rendering">
    <img *scPlaceholderLoading src="loading.gif">
  </sc-placeholder>

プレースホルダーの強化

Placeholderコンポーネントは、開発者のエクスペリエンスを向上させることができるいくつかのカスタマイズをサポートしています。

エラーコンポーネント

プレースホルダーでレンダリングエラーが発生した場合、プレースホルダーはプレースホルダーの内容の代わりにエラーコンポーネントを表示し、エラーの詳細をコンソールに記録します。このコンポーネントをカスタマイズするには、errorComponent propを使用して独自のReactコンポーネントに置き換えてください。

欠落しているコンポーネントコンポーネント

プレースホルダーにcomponentFactory不明なレンダリング名が含まれている場合 (たとえば、バックエンド開発者がFooレンダリングを作成してページに追加するが、まだfoo.component.tsがない場合)、レンダリングはAngularコンポーネントのmissingComponentComponentプロパティで定義されたMissingComponentコンポーネントに置き換えられます。デフォルトの実装は単純なメッセージですが、missingComponentComponentプロパティで独自のAngularコンポーネントを使用してカスタマイズできます。

非表示のレンダリングの処理

レンダリングがパーソナライゼーションルールによって非表示になっている場合、レンダリングはHiddenRenderingコンポーネントに置き換えられ、レンダリングにJSS実装がない場合のエラーメッセージが防止されます。独自のコンポーネントを作成し、hiddenRenderingComponentプロパティを使用してプレースホルダに提供できます。

この記事を改善するための提案がある場合は、 お知らせください!