拡張機能でモーダル ダイアログを作成する

Azure DevOps Services |Azure DevOps Server |Azure DevOps Server 2022

モーダル ダイアログは、Azure DevOps 拡張機能でフォーカスされたユーザー エクスペリエンスを作成するための強力な方法を提供します。 ダイアログ サービスを使用すると、ダイアログが閉じるまで、Azure DevOps インターフェイス全体とのユーザー操作をブロックするモーダル ダイアログを表示できます。 このアクションにより、ユーザーは重要なタスクを完了したり、必要な情報を提供したりできます。

拡張機能でモーダル ダイアログを使用して、次の作業を行います。

  • フォームを使用してユーザー入力を収集する
  • 重要なアクションの確認メッセージを表示する
  • ユーザーの注意が必要な詳細情報を表示する
  • マルチステップ プロセスをユーザーに案内する

Von Bedeutung

モーダル ダイアログを作成すると、拡張機能だけでなく、Azure DevOps ページ全体との対話がブロックされます。 この方法は、真のモーダル エクスペリエンスを提供しますが、ユーザー ワークフローを中断しないように注意深く使用する必要があります。

[前提条件]

カテゴリ 要件 詳細
拡張機能のセットアップ 拡張機能のプロジェクト作業 有効な vss-extension.json マニフェスト ファイル
Marketplace の登録 テストとデプロイのために Visual Studio Marketplace に登録された拡張機能
開発に関する知識 Azure DevOps 拡張機能の開発の基本について
開発環境 Node.js と npm npm がインストールされているNode.jsバージョン14以降
コード エディター Visual Studio Code またはその他の IDE を推奨
Azure DevOps アクセス テスト用の Azure DevOps 組織へのアクセス
必要なパッケージ 拡張機能 SDK インストール: npm install azure-devops-extension-sdk
拡張 API インストール: npm install azure-devops-extension-api
拡張機能のアクセス許可 マニフェスト スコープ vss-extension.jsonに適切なスコープを含める (例: "vso.work""vso.project"
SDK のインポート 必要なモジュール SDK のインポート: import * as SDK from "azure-devops-extension-sdk" とサービス: import { CommonServiceIds, IHostPageLayoutService } from "azure-devops-extension-api"

ダイアログ コンテンツ

まずは、拡張機能のマニフェストで型 ms.vss-web.control のコントリビューションを宣言します。 このコントリビューションは、ダイアログに表示されるコンテンツを表しています。

    {
        "id": "registration-form",
        "type": "ms.vss-web.control",
        "description": "The content to be displayed in the dialog",
        "targets": [],
        "properties": {
            "uri": "registration-form.html"
        }
    }

uri プロパティは、ダイアログのコンテンツ領域にレンダリングされるページを参照しています。

<!DOCTYPE html>
<html>
    <head></head>
    <body>
        <h2 id="header">Register now</h2>
        <p>
            <label>Name:</label>
            <input id="inpName" />
        </p>
        <p>
            <label>Date of birth:</label>
            <input id="inpDob" />
        </p>
        <p>
            <label>Email address:</label>
            <input id="inpEmail" />
        </p>
        <div id="root"></div>
        <script type="text/javascript" src="registration-form.js" charset="utf-8"></script>
    </body>
</html>

対応する JavaScript ファイル (registration-form.js) は、SDK を初期化し、ホストから渡されたすべての構成を取得し、準備ができたら SDK.notifyLoadSucceeded() を呼び出します。

import * as SDK from "azure-devops-extension-sdk";

SDK.init();
SDK.ready().then(() => {
    // Retrieve configuration passed through the dialog options
    const config = SDK.getConfiguration();
    console.log("Dialog configuration:", config);

    SDK.notifyLoadSucceeded();
});

importステートメントが実行時に正しく解決されるように、JavaScript を webpack などのツールでバンドルします。 HTML ページは、バンドルされた出力ファイル (たとえば、 registration-form.js) を参照します。

ダイアログを表示する

ダイアログを表示するには (たとえば、ユーザーがツール バーやメニューのアクションを選択した場合)、openCustomDialogIHostPageLayoutService メソッドを呼び出します。

import * as SDK from "azure-devops-extension-sdk";
import { CommonServiceIds, IHostPageLayoutService } from "azure-devops-extension-api";

const dialogService = await SDK.getService<IHostPageLayoutService>(CommonServiceIds.HostPageLayoutService);
const extensionCtx = SDK.getExtensionContext();

// Build absolute contribution ID for dialog content
const contributionId = `${extensionCtx.publisherId}.${extensionCtx.extensionId}.registration-form`;

// Show dialog
dialogService.openCustomDialog(contributionId, {
    title: "My Dialog",
    configuration: {
        // Pass initial data to the dialog content
        message: "Please fill out the registration form."
    },
    onClose: (result) => {
        if (result !== undefined) {
            console.log("Dialog result:", result);
        }
    }
});

ダイアログの結果を処理する

ダイアログ オプションの onClose コールバックは、ダイアログが閉じると結果を受け取ります。 configuration オプションを使用して、初期データをダイアログ コンテンツに渡します。

この例では、ホスト ページでカスタム ダイアログが開き、ダイアログが閉じたときに結果が処理されます。

import * as SDK from "azure-devops-extension-sdk";
import { CommonServiceIds, IHostPageLayoutService } from "azure-devops-extension-api";

const dialogService = await SDK.getService<IHostPageLayoutService>(CommonServiceIds.HostPageLayoutService);
const extensionCtx = SDK.getExtensionContext();
const contributionId = `${extensionCtx.publisherId}.${extensionCtx.extensionId}.registration-form`;

dialogService.openCustomDialog(contributionId, {
    title: "Registration Form",
    configuration: {
        defaultName: "Contoso User"
    },
    onClose: (result) => {
        if (result !== undefined) {
            // User completed the dialog
            console.log("Registration data:", JSON.stringify(result));
        } else {
            // User dismissed the dialog without completing
            console.log("Dialog was dismissed.");
        }
    }
});

ダイアログ コンテンツ ページで、 SDK.getConfiguration() を使用して、ホストから渡されたデータを取得します。 ダイアログ コンテンツ ページは、 onClose の結果を除き、ホストに直接通信することはできません。

import * as SDK from "azure-devops-extension-sdk";

SDK.init();
SDK.ready().then(() => {
    const config = SDK.getConfiguration();
    
    // Use configuration values passed from the host
    if (config.defaultName) {
        document.getElementById("inpName").value = config.defaultName;
    }

    SDK.notifyLoadSucceeded();
});

メッセージ ダイアログを表示する

[OK] ボタンと [キャンセル] ボタンを使用した簡単な確認ダイアログでは、カスタム ダイアログの代わりに openMessageDialog を使用します。

import * as SDK from "azure-devops-extension-sdk";
import { CommonServiceIds, IHostPageLayoutService } from "azure-devops-extension-api";

const dialogService = await SDK.getService<IHostPageLayoutService>(CommonServiceIds.HostPageLayoutService);

dialogService.openMessageDialog("Are you sure you want to proceed?", {
    title: "Confirm Action",
    showCancel: true,
    onClose: (result) => {
        // result is true if OK was selected, false if Cancel
        if (result) {
            console.log("User confirmed.");
        } else {
            console.log("User canceled.");
        }
    }
});

ダイアログに値を渡す

configuration オプションを使用して、初期値をダイアログ コンテンツに渡します。 ダイアログ コンテンツ ページは、 SDK.getConfiguration()を使用してこれらの値を取得します。

// Host page: pass configuration when opening the dialog
dialogService.openCustomDialog(contributionId, {
    title: "My Dialog Title",
    configuration: {
        itemId: 42,
        timestamp: new Date().getTime()
    },
    onClose: (result) => {
        if (result !== undefined) {
            console.log("Dialog result:", result);
        }
    }
});
// Dialog content page: retrieve configuration
import * as SDK from "azure-devops-extension-sdk";

SDK.init();
SDK.ready().then(() => {
    const config = SDK.getConfiguration();
    console.log("Item ID:", config.itemId);
    console.log("Timestamp:", config.timestamp);

    SDK.notifyLoadSucceeded();
});

ダイアログ ボタンをカスタマイズする

メッセージ ダイアログの場合、 okText プロパティと cancelText プロパティは、[OK] ボタンと [キャンセル] ボタンの代替タイトルを指定します。

dialogService.openMessageDialog("Do you want to save changes?", {
    title: "Save Changes",
    showCancel: true,
    okText: "Yes",
    cancelText: "No",
    onClose: (result) => {
        if (result) {
            console.log("User selected Yes.");
        }
    }
});

簡易無視を有効にする

カスタム ダイアログの場合は、 lightDismisstrue に設定して、ダイアログの外側を選択すると閉じます。

dialogService.openCustomDialog(contributionId, {
    title: "My Dialog Title",
    lightDismiss: true,
    onClose: (result) => {
        console.log("Dialog closed.");
    }
});

ライト 無視は既定で有効になっています (true)。 ユーザーがダイアログを明示的に閉じる必要 false に設定します。

疑問がある場合、または詳しい情報を探している場合は、次のいずれかのページをご覧ください。