共用方式為


在擴充功能中建立模態對話框

Azure DevOps 服務 |Azure DevOps Server |Azure DevOps Server 2022 |Azure DevOps Server 2020

模態對話框是一種強大的方法,可在 Azure DevOps 擴充功能中建立專注的使用者體驗。 對話服務允許你呈現一個模態對話框,阻擋使用者與整個 Azure DevOps 介面的互動,直到對話被關閉為止。 此動作可確保使用者完成重要工作或提供必要的資訊。

於您的擴充功能中使用模態對話框來:

  • 透過表單收集使用者輸入
  • 顯示重要動作的確認訊息
  • 顯示需要使用者注意的詳細資訊
  • 引導使用者完成多個步驟的流程

這很重要

當你建立 modal 對話框時,它們會阻擋與整個 Azure DevOps 頁面的互動,不只是你的擴充功能。 此方法提供真正的模態體驗,但您應謹慎使用,以避免中斷使用者的工作流程。

先決條件

類別 要求 詳細資訊
擴充功能設定 工作擴展專案 有效的 vss-extension.json 資訊清單檔案
Marketplace 註冊 向 Visual Studio Marketplace 註冊以進行測試和部署的延伸模組
開發知識 瞭解 Azure DevOps 擴充功能開發基本概念
開發環境 Node.js 和 npm Node.js 已安裝 npm 的 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"

對話框內容

若要開始,請在延伸模組指令清單中宣告 類型 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>
        <script src="node_modules/azure-devops-extension-sdk/lib/SDK.js"></script>
    </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>
        <script type="module">
            import * as SDK from "azure-devops-extension-sdk";
            
            SDK.init();
            const registrationForm = (function() {
                const callbacks = [];
                
                function inputChanged() {
                    // Execute registered callbacks
                    for(let i = 0; i < callbacks.length; i++) {
                        callbacks[i](isValid());
                    }
                }
                
                function isValid() {
                    // Check whether form is valid or not
                    return !!(name.value) && !!(dateOfBirth.value) && !!(email.value);
                }
                
                function getFormData() {
                    // Get form values
                    return {
                        name: name.value,
                        dateOfBirth: dateOfBirth.value,
                        email: email.value  
                    };
                }

                const name = document.getElementById("inpName");
                const dateOfBirth = document.getElementById("inpDob");
                const email = document.getElementById("inpEmail");
                
                name.addEventListener("change", inputChanged);
                dateOfBirth.addEventListener("change", inputChanged);
                email.addEventListener("change", inputChanged);
                
                return {
                    isFormValid: function() {
                        return isValid();   
                    },
                    getFormData: function() {
                        return getFormData();
                    },
                    attachFormChanged: function(cb) {
                         callbacks.push(cb);
                    }
                };
            })();
            
            // Register form object to be used across this extension
            SDK.register("registration-form", registrationForm);
        </script>
    </body>
</html>

顯示對話框

要顯示對話框(例如使用者在工具列或選單中選擇動作時),請在對話服務的實例中呼叫該 openDialog 函式:

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

SDK.getService(SDK.CommonServiceIds.Dialog).then((dialogService) => {
    const extensionCtx = SDK.getExtensionContext();
    // Build absolute contribution ID for dialogContent
    const contributionId = `${extensionCtx.publisherId}.${extensionCtx.extensionId}.registration-form`;

    // Show dialog
    const dialogOptions = {
        title: "My Dialog",
        width: 800,
        height: 600
    };

    dialogService.openDialog(contributionId, dialogOptions);
});

進階對話框功能

選取 [確定] 按鈕時,可以呼叫函式。 您可以在顯示對話方塊時提供的選項中進行設定 getDialogResult 來指定此功能。

如果呼叫 getDialogResult 傳回非空值,則此值會傳遞至由 okCallback 指定的函式(也在選項中),並關閉對話方塊。

在此範例中,當表單上的輸入變更時,會呼叫 attachFormChanged 回調函數。 根據表單是否有效,已啟用或停用 [確定] 按鈕。

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

SDK.getService(SDK.CommonServiceIds.Dialog).then((dialogService) => {
    let registrationForm;
    const extensionCtx = SDK.getExtensionContext();
    const contributionId = `${extensionCtx.publisherId}.${extensionCtx.extensionId}.registration-form`;

    const dialogOptions = {
        title: "Registration Form",
        width: 800,
        height: 600,
        getDialogResult: () => {
            // Get the result from registrationForm object
            return registrationForm ? registrationForm.getFormData() : null;
        },
        okCallback: (result) => {
            // Log the result to the console
            console.log(JSON.stringify(result));
        }
    };

    dialogService.openDialog(contributionId, dialogOptions).then((dialog) => {
        // Get registrationForm instance which is registered in registration-form.html
        dialog.getContributionInstance("registration-form").then((registrationFormInstance) => {
        
            // Keep a reference of registration form instance (to be used previously in dialog options)
            registrationForm = registrationFormInstance;
            
            // Subscribe to form input changes and update the Ok enabled state
            registrationForm.attachFormChanged((isValid) => {
                dialog.updateOkButton(isValid);
            });
            
            // Set the initial ok enabled state
            registrationForm.isFormValid().then((isValid) => {
                dialog.updateOkButton(isValid);
            });
        });                            
    });
});

控制 [確定] 按鈕

一開始,[確定] 按鈕會停用。 不過,您可以在對話框中呼叫 updateOkButton 方法,以啟用/停用此按鈕:

    dialogService.openDialog(contributionId, dialogOptions).then((dialog) => {
        // Set true/false to enable/disable ok button
        dialog.updateOkButton(true); 
    });

將值傳遞至對話框

當您在主機對話方塊中開啟對話方塊內容時,可以將初始值傳遞至對話方塊內容。

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

對話方塊開啟時,必須指定下列選項才能傳遞 myId

    const dialogOptions = {
        title: "My Dialog Title",
        width: 800,
        height: 600,
        urlReplacementObject: { myId: new Date().getTime() }
    };

自訂對話框按鈕

okTextcancelText 屬性可用來指定 [確定] 和 [取消] 按鈕的替代標題:

    const dialogOptions = {
        title: "My Dialog Title",
        width: 800,
        height: 600,
        okText: "Yes",
        cancelText: "No" 
    };

若要不顯示對話方塊上的任何按鈕,您可以將 屬性設定 buttons[]

    const dialogOptions = {
        title: "My Dialog Title",
        width: 800,
        height: 600,
        buttons: []
    };

如果您有問題或正在尋找詳細資訊,請考慮前往下列其中一個區域: