コード コンポーネントの作成についての概要

完了

Power Apps には、アプリ作成のための機能が数多く組み込まれていますが、特殊な要件を満たすためにカスタムなユーザー エクスペリエンスを作成することが必要になる場合もあります。 たとえば、割合の値をゲージに置き換える、ID ではなくバー コードを表示する、または既存のコントロールをドラッグ アンド ドロップ グリッド ビューなど、より多くの機能を持つコントロールに置き換えることがあります。 また、React や Angular など、他の Web フレームワークで書かれた既存のコンポーネントについて、Power Apps Component Framework を折り返すことができます。

これらのコンポーネントを作成すると、幅広い最新の Web 開発エコシステム (プラットフォームの標準部分であるかのように、アプリ開発者が自身のコードを使用してアプリを構築できる、使い慣れたライブラリ、フレームワーク、および他のツール、およびフォームに機能を組み込むことができるパッケージ) を活用できます。

カスタム Power Apps コンポーネントは、作成にカスタム コードを必要とするため、コード コンポーネントと呼ばれることがよくあります。 それらは、マニフェスト、実装、リソースという 3 つの要素で構成されます。

次の演習では、ある要件を満たすために、企業でカスタム コード コンポーネントを作成します。 アプリケーションのフォームに表示されるいくつかのフィールドに対し、ユーザーが手動でデータの編集を開始するまで、その値を読み取り専用にしておく必要があるとします。 開発チームは組み込みのどのコントロールでも要件を満たすことができないと判断し、カスタム コード コンポーネントを作成することにしました。

そのため、次の画像に示すような、編集可能なフィールド カスタム コンポーネントを作成します。 この値を、ユーザーが編集を選択するまで読み取り専用にする必要があります。

カスタム コード コンポーネントのスクリーンショット。

このコンポーネントは、ホスト アプリからの変更をリッスンしてから、ホスト アプリにプッシュされる変更をユーザーが行うのを許可します。 このコンポーネントを作成するには、次の手順のようにします。

Power Platform CLI をインストールする

コード コンポーネントを構築するためにコンピューターを準備する場合は、次の手順を実行します。

  1. Npm (Node.js に付属) または Node.js (npm に付属) をインストールします。 LTS (長期サポート) バージョンのご利用をお勧めします。

  2. Visual Studio Code をインストールします。

  3. Power Platform Tools 拡張機能をインストールします。

新しいコンポーネント プロジェクトを作成する

新しいコンポーネント プロジェクトを作成するには、次の手順のようにします。

コンポーネントを構築するディレクトリを作成します。 このサンプルではコンポーネントを C:\source\Editable-pcf に配置しますが、独自のディレクトリを作成できます。 独自のディレクトリを作成するには、Visual Studio Code を使用します。

  1. Visual Studio Code を起動します。

  2. ターミナル新しいターミナルの順に選択します。

    Visual Studio Code の新しいターミナルの選択を示すスクリーンショット。

  3. ディレクトリをソース フォルダーに変更します。

    cd source
    
  4. ソース ディレクトリから、hello-pcf という名前のディレクトリを作成します。

    md editable-pcf
    
  5. ディレクトリを hello-pcf に変更します。

    cd editable-pcf
    

    ディレクトリの作成と変更を行うコマンドを使用しているターミナルを示すスクリーンショット。

  6. Power Platform CLI で次のコマンドを使用して、コンポーネント プロジェクトを初期化します。

    pac pcf init --namespace SampleNamespace --name EditablePCF --template field
    

    次の図では、表示される出力の例を示します。

    pcf init コマンドを使用しているターミナルを示すスクリーンショット。

  7. コマンドnpm install を使用して、プロジェクト ビルド ツールをインストールします。 警告がいくつか表示される場合がありますが、無視してかまいません。

    npm install
    
  8. 次のコマンドを実行して、Visual Studio Code でプロジェクトを開きます。

    code -a .
    
  9. プロジェクトの内容は、次の図のようになります。

    プロジェクト ファイルを示すスクリーンショット。

コード コンポーネントのマニフェストを更新する

コントロールを正確に表すように、マニフェスト ファイルを更新します。

  1. EditablePCF フォルダーを展開し、ControlManifest.Input.xml ファイルを開きます。

    コントロール マニフェスト入力 XML ファイルのスクリーンショット。

  2. バージョンを 1.0.0 に変更し、description-key を Edits project name に変更します。

    コントロールに加えた変更を示すスクリーンショット。

  3. property ノードを探します。

  4. name 値を Name、display-name-key を Name、description-key を A name に変更します。

    property ノードに加えた変更を示すスクリーンショット。

  5. resources ノードを見つけます。

  6. 後で作成する editable-pcf.css という名前の CSS ファイルへの参照を含めます。

    <css path="css/editable-pcf.css" order="1" />
    

    リソース ノードに加えた変更を示すスクリーンショット。

  7. ファイルを選択して保存をクリックし、変更を保存します。

コード コンポーネントにスタイル設定を追加する

コード コンポーネントにスタイル設定を追加するには、以下の手順を実行します。

  1. ControlManifest.Input.xml ファイルが選択されたままになっていることを確認し、新しいフォルダーを選択します。

    新しいフォルダーの追加ボタンを示すスクリーンショット。

  2. 新しいフォルダーに css という名前を付けます。

  3. 作成した css フォルダーを選択し、新しいファイルを選択します。

  4. 新しいファイルに editable-pcf.css という名前を付けます。

  5. 作成した新しい editable-pcf.css ファイルを開き、次の CSS スニペットを貼り付けます。

    .SampleNamespace\.HelloPCF {
          font-size: 1.5em;
        }
    
  6. CSS ファイルの内容は、次の図のようになります。

    CSS ファイルの内容を示すスクリーンショット。

  7. ファイルを選択して保存を選択します。

コード コンポーネントをビルドする

コンポーネント ロジックを実装する前に、コンポーネント上でビルドを実行する必要があります。 これにより、適切な TypeScript タイプが、ControlManifest.xml ドキュメントのプロパティに合わせて生成されることを確認します。

ターミナルに戻り、次のコマンドを使用してプロジェクトをビルドします。

npm run build

コンパイルされたコンポーネントは、out/controls/EditablePCF ディレクトリに作成されます。 ビルド成果物には次のものが含まれます。

  • css フォルダー

  • bundle.js - バンドルされたコンポーネントのソース コード

  • ControlManifest.xml - Microsoft Dataverse 組織にアップロードされる実際のコンポーネント マニフェスト ファイル

    フォルダーの内容を示すスクリーンショット。

コード コンポーネントのロジックを実装する

コード コンポーネントのロジックを実装するには、次の手順を実行します。

  1. index.ts ファイルを開きます。

  2. コンストラクター メソッドの上に、次のプライベート変数を挿入します。

    // The PCF context object\
    private context: ComponentFramework.Context<IInputs>;
    // The wrapper div element for the component\
    private container: HTMLDivElement;
    // The callback function to call whenever your code has made a change to a bound or output property\
    private notifyOutputChanged: () => void;
    // Flag to track if the component is in edit mode or not\
    private isEditMode: boolean;
    // Tracking variable for the name property\
    private name: string | null;
    

    index.ts ファイルに追加されたプライベート変数を示すスクリーンショット。

  3. init メソッドを見つけ、次のメソッドで置き換えます。

    public init(context: ComponentFramework.Context<IInputs>, notifyOutputChanged: () => void, state: ComponentFramework.Dictionary, container: HTMLDivElement) {
    
    // Track all the things
    
    this.context = context;
    
    this.notifyOutputChanged = notifyOutputChanged;
    
    this.container = container;
    
    this.isEditMode = false;
    
    }
    
  4. 次のスニペットを init メソッドに追加します。 このスニペットによって、プロジェクト名を保持する span が作成されます。

    // Create the span element to hold the project name
    
    const message = document.createElement("span");
    
    message.innerText = `Project name ${this.isEditMode ? "" :context.parameters.Name.raw}`;
    
  5. 次のスニペットを init メソッドに追加します。 このコードによって、名前を編集するためのテキスト ボックスが作成されます。

    // Create the textbox to edit the name
    
    const textbox = document.createElement("input");
    
    textbox.type = "text";
    
    textbox.style.display = this.isEditMode ? "block" : "none";
    
  6. init メソッドに次の if ステートメントを追加します。

    if (context.parameters.Name.raw) {
    }
    
  7. if ステートメント内に次のスニペットを追加します。 このスニペットにより、テキスト ボックスの値が設定され、テキスト ボックスと div 内のメッセージが折り返されます。

    textbox.value = context.parameters.Name.raw;
    
    // Wrap the two above elements in a div to box out the content
    
    const messageContainer = document.createElement("div");
    
    messageContainer.appendChild(message);
    
    messageContainer.appendChild(textbox);
    
  8. if ステートメント内に次のスニペットを追加します。 このスニペットにより、編集モードと読み取りモードを切り替えるボタンが作成されます。

    // Create the button element to switch between edit and read modes
    
    const button = document.createElement("button");
    
    button.textContent = this.isEditMode ? "Save" : "Edit";
    
    button.addEventListener("click", () => { this.buttonClick(); });
    
  9. if ステートメント内に次のスニペットを追加します。 このスニペットにより、メッセージ コンテナーとボタンがメイン コンテナーに追加されます。

    // Add the message container and button to the overall control container
    
    this.container.appendChild(messageContainer);
    
    this.container.appendChild(button);
    
  10. init メソッドは、次の図のようになります。

    init メソッドの内容を示すスクリーンショット。

  11. ボタン選択ハンドラー メソッドを追加します。 次のメソッドを init メソッドの下に追加します。

    public buttonClick() {
    }
    
  12. buttonClick メソッド内に次のスニペットを追加します。 このスニペットにより、DOM クエリを介してコントロールが取得されます。

    // Get our controls via DOM queries
    
    const textbox = this.container.querySelector("input")!;
    
    const message = this.container.querySelector("span")!;
    
    const button = this.container.querySelector("button")!;
    
  13. buttonClick メソッド内に次のスニペットを追加します。 編集モードの場合、このスニペットによりテキスト値が name にコピーされ、notify メソッドが呼び出されます。

    // If not in edit mode, copy the current name value to the textbox
    
    if (!this.isEditMode) {
    
    textbox.value = this.name ?? "";
    
    } else if (textbox.value != this.name) {
    
    // if in edit mode, copy the textbox value to name and call the notify callback
    
    this.name = textbox.value;
    
    this.notifyOutputChanged();
    }
    
  14. buttonClick メソッド内に次のスニペットを追加します。 このスニペットにより、モード フラグが切り替えられます。

    // flip the mode flag
    this.isEditMode = !this.isEditMode;
    
    
  15. buttonClick メソッド内に次のスニペットを追加します。 このスニペットにより、変更に基づいて新しい出力が設定されます。

    // Set up the new output based on changes
    
    message.innerText = `Project name ${this.isEditMode ? "" : this.name}`;
    
    textbox.style.display = this.isEditMode ? "inline" : "none";
    
    textbox.value = this.name ?? "";
    
    button.textContent = this.isEditMode ? "Save" : "Edit";
    
    
  16. buttonClick メソッドは、次の図のようになります。

    buttonClick メソッドの内容を示すスクリーンショット。

  17. updateView メソッドを見つけ、次のメソッドで置き換えます。

    public updateView(context: ComponentFramework.Context<IInputs>): void {
    
    // Checks for updates coming in from outside
    
    this.name = context.parameters.Name.raw;
    const message = this.container.querySelector("span")!;
    message.innerText = `Project name ${this.name}`;
    }
    
  18. 置き換える getOutputs メソッドを見つけ、次のメソッドで置き換えます。

    public getOutputs(): IOutputs {
    return {
    // If our name variable is null, return undefined instead
    Name: this.name ?? undefined
    };
    }
    
  19. destroy メソッドを見つけ、次のメソッドで置き換えます。

    public destroy() {
    // Remove the event listener we created in init
    this.container.querySelector("button")!.removeEventListener("click", this.buttonClick);
    }
    
  20. updateView、getOutputs、destroy の各メソッドは、次の図のようになります。

    updateView、getOutputs、destroy の各メソッドの内容を示すスクリーンショット。

コード コンポーネントをリビルドして実行する

コード コンポーネントをリビルドして実行するには、次の手順のようにします。

  1. コンポーネントのロジックが実装されたので、ターミナルに戻り、次のコマンドを使用してリビルドします。

    npm run build
    
  2. ビルドが成功します。

    ビルド結果を示すスクリーンショット。

  3. 次のコマンドを実行して、Node のテスト ハーネスでコンポーネントを実行します。

    npm start
    

    npm start watch コマンドを使用してウォッチ モードを有効にすることにより、テスト ハーネスを再起動しなくても、次の資産に対する変更が自動的に行われるようにすることもできます。

    • index.ts ファイル。

    • ControlManifest.Input.xml ファイル

    • index.ts にインポートされたライブラリ

    • マニフェスト ファイルに列記されているすべてのリソース

  4. 新しいブラウザー ウィンドウに、テスト ハーネスが読み込まれます。 (ウィンドウは自動的に開きますが、コマンド ウィンドウで見つかったアドレスを参照することもできます)。

  5. 編集を選択します。

    テスト ハーネスの編集ボタンを示すスクリーンショット。

  6. Project One と入力し、保存を選択します。

  7. コンテナーのサイズは変更できます。

  8. テスト ハーネスは次の図のようになります。

    テスト ハーネス内のコントロールを示すスクリーンショット。

  9. テスト ハーネスのブラウザー セッションを閉じます。

  10. ターミナルに戻り、[CONTROL] + C キーを押したまま Watcher を停止します。

  11. Y と入力し、[ENTER] を押します。