Skip to content

Commit 08558d0

Browse files
committed
uuf fix
1 parent 8f96e87 commit 08558d0

File tree

1 file changed

+78
-50
lines changed

1 file changed

+78
-50
lines changed

docs/extend/develop/using-host-dialog.md

Lines changed: 78 additions & 50 deletions
Original file line numberDiff line numberDiff line change
@@ -1,29 +1,50 @@
11
---
22
ms.subservice: azure-devops-ecosystem
3-
title: Modal Dialog | Extensions for Azure DevOps
4-
description: Use the modal dialog provided by the host for Azure DevOps.
3+
title: Create modal dialogs in Azure DevOps extensions
4+
description: Learn how to implement modal dialogs using HostDialogService in Azure DevOps extensions with the azure-devops-extension-sdk package. Build interactive dialogs with custom content, validation, and user interactions.
55
ms.assetid: 59748E0E-2D5E-FF79-ED0E-4B76037A8010
6-
ms.topic: conceptual
6+
ms.topic: how-to
7+
ai-usage: ai-assisted
78
monikerRange: '<= azure-devops'
89
ms.author: chcomley
910
author: chcomley
10-
ms.date: 09/19/2019
11+
ms.date: 07/02/2025
12+
# customer-intent: As an Azure DevOps extension developer, I want to create modal dialogs that block user interaction with the entire page so I can collect user input, display forms, and provide focused user experiences in my extensions.
1113
---
1214

13-
# Modal dialog
15+
# Create modal dialogs in extensions
1416

1517
[!INCLUDE [version-lt-eq-azure-devops](../../includes/version-lt-eq-azure-devops.md)]
1618

17-
The HostDialogService enables you to present a modal dialog to the user and prevent interaction with all parts of web access until the dialog is dismissed.
19+
Modal dialogs provide a powerful way to create focused user experiences in Azure DevOps extensions. The HostDialogService lets you present a modal dialog that blocks user interaction with the entire Azure DevOps interface until the dialog gets dismissed. This action ensures that users complete important tasks or provide required information.
1820

19-
[!INCLUDE [extension-docs-new-sdk](../../includes/extension-docs-new-sdk.md)]
21+
Use modal dialogs in your extensions to:
22+
- Collect user input through forms
23+
- Display confirmation messages for critical actions
24+
- Show detailed information that requires user attention
25+
- Guide users through multi-step processes
2026

21-
<div class="alert alert-info">
22-
In contrast to the standard dialog control, a modal dialog presented via the HostDialogService prevents interaction by the user on the entire page, not just within the extension.
23-
</div>
27+
> [!IMPORTANT]
28+
> When you create modal dialogs with `HostDialogService`, they block interaction with the entire Azure DevOps page, not just your extension. This approach provides a true modal experience but you should use it thoughtfully to avoid disrupting the user workflow.
2429
30+
## Prerequisites
2531

26-
### Dialog contents
32+
Before you can create modal dialogs in your Azure DevOps extension, ensure you have the following:
33+
34+
| Category | Requirement | Details |
35+
|----------|-------------|---------|
36+
| **Extension setup** | Working extension project | A valid `vss-extension.json` manifest file |
37+
| | Marketplace registration | Extension registered with Visual Studio Marketplace for testing and deployment |
38+
| | Development knowledge | Understanding of [Azure DevOps extension development basics](../get-started/node.md) |
39+
| **Development environment** | Node.js and npm | Node.js version 14 or later with npm installed |
40+
| | Code editor | Visual Studio Code or other IDE recommended |
41+
| | Azure DevOps access | Access to an Azure DevOps organization for testing |
42+
| **Required packages** | Extension SDK | Install: `npm install azure-devops-extension-sdk` |
43+
| | Extension API | Install: `npm install azure-devops-extension-api` |
44+
| **Extension permissions** | Manifest scopes | Include appropriate scopes in `vss-extension.json`, for example: `"vso.work"`, `"vso.project"` |
45+
| **SDK imports** | Required modules | Import SDK and services: `import * as SDK from "azure-devops-extension-sdk"` and `import { CommonServiceIds, IHostDialogService } from "azure-devops-extension-api"` |
46+
47+
## Dialog contents
2748

2849
To start, declare a contribution of type `ms.vss-web.control` in your extension manifest. This contribution represents the content displayed within the dialog.
2950

@@ -45,7 +66,7 @@ The `uri` property references a page that is rendered within the content area of
4566
<!DOCTYPE html>
4667
<html>
4768
<head>
48-
<script src="sdk/scripts/VSS.SDK.js"></script>
69+
<script src="node_modules/azure-devops-extension-sdk/lib/SDK.js"></script>
4970
</head>
5071
<body>
5172
<h2 id="header">Register now</h2>
@@ -61,14 +82,16 @@ The `uri` property references a page that is rendered within the content area of
6182
<label>Email address:</label>
6283
<input id="inpEmail" />
6384
</p>
64-
<script>
65-
VSS.init();
66-
var registrationForm = (function() {
67-
var callbacks = [];
85+
<script type="module">
86+
import * as SDK from "azure-devops-extension-sdk";
87+
88+
SDK.init();
89+
const registrationForm = (function() {
90+
const callbacks = [];
6891
6992
function inputChanged() {
7093
// Execute registered callbacks
71-
for(var i = 0; i < callbacks.length; i++) {
94+
for(let i = 0; i < callbacks.length; i++) {
7295
callbacks[i](isValid());
7396
}
7497
}
@@ -87,9 +110,9 @@ The `uri` property references a page that is rendered within the content area of
87110
};
88111
}
89112
90-
var name = document.getElementById("inpName");
91-
var dateOfBirth = document.getElementById("inpDob");
92-
var email = document.getElementById("inpEmail");
113+
const name = document.getElementById("inpName");
114+
const dateOfBirth = document.getElementById("inpDob");
115+
const email = document.getElementById("inpEmail");
93116
94117
name.addEventListener("change", inputChanged);
95118
dateOfBirth.addEventListener("change", inputChanged);
@@ -109,24 +132,26 @@ The `uri` property references a page that is rendered within the content area of
109132
})();
110133
111134
// Register form object to be used across this extension
112-
VSS.register("registration-form", registrationForm);
135+
SDK.register("registration-form", registrationForm);
113136
</script>
114137
</body>
115138
</html>
116139
```
117140

118-
### Showing the dialog
141+
## Show the dialog
119142

120-
To show the dialog (for example, when a user selects an action on a toolbar or menu), call the `openDialog` function on an instance of the HostDialogService, passing the fully-qualified identifier of the dialog content, for example `my-publisher.my-extension.registration-form` and any dialog options:
143+
To show the dialog (for example, when a user selects an action on a toolbar or menu), call the `openDialog` function on an instance of the HostDialogService, passing the fully qualified identifier of the dialog content, for example `my-publisher.my-extension.registration-form` and any dialog options:
121144

122145
```javascript
123-
VSS.getService(VSS.ServiceIds.Dialog).then(function(dialogService) {
124-
var extensionCtx = VSS.getExtensionContext();
146+
import * as SDK from "azure-devops-extension-sdk";
147+
148+
SDK.getService<IHostDialogService>(CommonServiceIds.HostDialogService).then((dialogService) => {
149+
const extensionCtx = SDK.getExtensionContext();
125150
// Build absolute contribution ID for dialogContent
126-
var contributionId = extensionCtx.publisherId + "." + extensionCtx.extensionId + ".registration-form";
151+
const contributionId = `${extensionCtx.publisherId}.${extensionCtx.extensionId}.registration-form`;
127152

128153
// Show dialog
129-
var dialogOptions = {
154+
const dialogOptions = {
130155
title: "My Dialog",
131156
width: 800,
132157
height: 600
@@ -136,48 +161,51 @@ To show the dialog (for example, when a user selects an action on a toolbar or m
136161
});
137162
```
138163

139-
### Showing the dialog (advanced)
164+
## Advanced dialog features
140165

141166
A function can be called when the OK button is selected. This function is specified by `getDialogResult` in the options you provide when showing the dialog.
142167

143168
If a call to `getDialogResult` returns a non-null value, this value is then passed to the function specified by `okCallback` (also in the options) and the dialog is closed.
144169

145-
In this example, the `attachFormChanged` callback gets called when inputs on the form change. Based on the whether the form is valid or not, the OK button is enabled or disabled.
170+
In this example, the `attachFormChanged` callback gets called when inputs on the form change. Based whether the form is valid or not, the OK button is enabled or disabled.
146171

147172
```javascript
148-
VSS.getService(VSS.ServiceIds.Dialog).then(function(dialogService) {
149-
var registrationForm;
150-
var extensionCtx = VSS.getExtensionContext();
151-
var contributionId = extensionCtx.publisherId + "." + extensionCtx.extensionId + ".registration-form";
152-
153-
var dialogOptions = {
173+
import * as SDK from "azure-devops-extension-sdk";
174+
import { CommonServiceIds, IHostDialogService } from "azure-devops-extension-api";
175+
176+
SDK.getService<IHostDialogService>(CommonServiceIds.HostDialogService).then((dialogService) => {
177+
let registrationForm: any;
178+
const extensionCtx = SDK.getExtensionContext();
179+
const contributionId = `${extensionCtx.publisherId}.${extensionCtx.extensionId}.registration-form`;
180+
181+
const dialogOptions = {
154182
title: "Registration Form",
155183
width: 800,
156184
height: 600,
157-
getDialogResult: function() {
185+
getDialogResult: () => {
158186
// Get the result from registrationForm object
159187
return registrationForm ? registrationForm.getFormData() : null;
160188
},
161-
okCallback: function (result) {
189+
okCallback: (result: any) => {
162190
// Log the result to the console
163191
console.log(JSON.stringify(result));
164192
}
165193
};
166194

167-
dialogService.openDialog(contributionId, dialogOptions).then(function(dialog) {
195+
dialogService.openDialog(contributionId, dialogOptions).then((dialog) => {
168196
// Get registrationForm instance which is registered in registrationFormContent.html
169-
dialog.getContributionInstance("registration-form").then(function (registrationFormInstance) {
197+
dialog.getContributionInstance("registration-form").then((registrationFormInstance) => {
170198

171199
// Keep a reference of registration form instance (to be used previously in dialog options)
172200
registrationForm = registrationFormInstance;
173201

174202
// Subscribe to form input changes and update the Ok enabled state
175-
registrationForm.attachFormChanged(function(isValid) {
203+
registrationForm.attachFormChanged((isValid: boolean) => {
176204
dialog.updateOkButton(isValid);
177205
});
178206

179207
// Set the initial ok enabled state
180-
registrationForm.isFormValid().then(function (isValid) {
208+
registrationForm.isFormValid().then((isValid: boolean) => {
181209
dialog.updateOkButton(isValid);
182210
});
183211
});
@@ -186,20 +214,20 @@ In this example, the `attachFormChanged` callback gets called when inputs on the
186214

187215
```
188216

189-
### Enabling or disabling the OK button
217+
## Control the OK button
190218

191219
Initially, the OK button is disabled. However, you can enable/disable this button by calling the `updateOkButton` method on the dialog:
192220

193221
```javascript
194-
dialogService.openDialog(contributionId, dialogOptions).then(function(dialog) {
222+
dialogService.openDialog(contributionId, dialogOptions).then((dialog) => {
195223
// Set true/false to enable/disable ok button
196224
dialog.updateOkButton(true);
197225
});
198226
```
199227

200-
### Passing values to the dialog control
228+
## Pass values to the dialog
201229

202-
It is possible pass initial values to dialog content when it is opened in the host dialog.
230+
It's possible pass initial values to dialog content when it is opened in the host dialog.
203231

204232
```json
205233
{
@@ -216,20 +244,20 @@ It is possible pass initial values to dialog content when it is opened in the ho
216244
When the dialog is opened, following options need to be specified to pass `myId`:
217245

218246
```javascript
219-
var dialogOptions = {
247+
const dialogOptions = {
220248
title: "My Dialog Title",
221249
width: 800,
222250
height: 600,
223251
urlReplacementObject: { myId: new Date().getTime() }
224252
};
225253
```
226254

227-
### Customizing the dialog buttons
255+
## Customize dialog buttons
228256

229257
The `okText` and `cancelText` attributes can be used to specify alternate titles for the OK and Cancel buttons:
230258

231259
```javascript
232-
var dialogOptions = {
260+
const dialogOptions = {
233261
title: "My Dialog Title",
234262
width: 800,
235263
height: 600,
@@ -241,15 +269,15 @@ The `okText` and `cancelText` attributes can be used to specify alternate titles
241269
To not show any buttons on the dialog, you can set the `buttons` attribute to `[]`:
242270

243271
```javascript
244-
var dialogOptions = {
272+
const dialogOptions = {
245273
title: "My Dialog Title",
246274
width: 800,
247275
height: 600,
248276
buttons: []
249277
};
250278
```
251279

252-
### More information
280+
## Related resources
253281

254282
If you have a question or are looking for more information, consider going to one of the following areas:
255283

0 commit comments

Comments
 (0)