Note
Access to this page requires authorization. You can try signing in or changing directories.
Access to this page requires authorization. You can try changing directories.
Azure DevOps Services | Azure DevOps Server | Azure DevOps Server 2022
Use extensions to customize the work item form by adding groups, pages, menu actions, observers, or custom controls.
Tip
If you're starting a new Azure DevOps extension, try these maintained sample collections first—they work with current product builds and cover modern scenarios (for example, adding tabs on pull request pages).
- Azure DevOps extension sample (GitHub)—a compact starter sample that demonstrates common extension patterns: https://github.com/microsoft/azure-devops-extension-sample
- Azure DevOps extension samples (legacy collection and contributions guide)—install to inspect UI targets, or view the source: https://marketplace.visualstudio.com/items/ms-samples.samples-contributions-guide and https://github.com/Microsoft/vso-extension-samples/tree/master/contributions-guide
- Microsoft Learn samples (browse Azure DevOps samples)—curated, up-to-date samples across Microsoft docs: /samples/browse/?terms=azure%20devops%20extension
If a sample doesn't work in your organization, install it into a personal or test organization and compare the extension manifest's target IDs and API versions with the current docs. For reference and APIs, see:
- Add a group
- Add a page (tab)
- Add a menu action
- Add a custom control
- Listen for events
- Configure contributions
For the full source code, see the UI example in the Azure DevOps extension samples on GitHub.
Tip
For the latest extension development guidance, including theming and migration from VSS.SDK, see the Azure DevOps Extension SDK developer portal.
Add a group
To add a group to the main page, add a contribution to your extension manifest with type ms.vss-work-web.work-item-form-group targeting ms.vss-work-web.work-item-form:
"contributions": [
{
"id": "sample-work-item-form-group",
"type": "ms.vss-work-web.work-item-form-group",
"description": "Custom work item form group",
"targets": [
"ms.vss-work-web.work-item-form"
],
"properties": {
"name": "My Group",
"uri": "workItemGroup.html",
"height": 600
}
}
]
Properties
| Property | Description |
|---|---|
name |
Text that appears on the group. |
uri |
URI to the HTML page loaded in the IFrame. |
height |
(Optional) Height of the group. Default is 100%. |
JavaScript sample
This example registers a provider that responds to work item form events. It uses the WorkItemFormService to read field values when the work item loads.
import { IWorkItemFormService, WorkItemTrackingServiceIds } from "azure-devops-extension-api/WorkItemTracking";
import * as SDK from "azure-devops-extension-sdk";
async function getWorkItemFormService(): Promise<IWorkItemFormService> {
return await SDK.getService<IWorkItemFormService>(WorkItemTrackingServiceIds.WorkItemFormService);
}
SDK.init();
SDK.ready().then(() => {
SDK.register(SDK.getContributionId(), () => {
return {
// Called when the active work item is modified
onFieldChanged: (args) => {
console.log("onFieldChanged", JSON.stringify(args));
},
// Called when a new work item is being loaded in the UI
onLoaded: async (args) => {
const service = await getWorkItemFormService();
const values = await service.getFieldValues([
"System.Id", "System.Title", "System.State", "System.CreatedDate"
]);
console.log("onLoaded", JSON.stringify(values));
},
// Called when the active work item is being unloaded in the UI
onUnloaded: (args) => {
console.log("onUnloaded", JSON.stringify(args));
},
// Called after the work item has been saved
onSaved: (args) => {
console.log("onSaved", JSON.stringify(args));
},
// Called when the work item is reset to its unmodified state (undo)
onReset: (args) => {
console.log("onReset", JSON.stringify(args));
},
// Called when the work item has been refreshed from the server
onRefreshed: (args) => {
console.log("onRefreshed", JSON.stringify(args));
}
};
});
});
Events
| Event | Event description | Argument | Argument description |
|---|---|---|---|
onFieldChanged |
Fired after a field has changed. If the field change ran rules that updated other fields, all these changes are part of a single event. | ID | The ID of the work item |
changedFields |
Array with the reference name of all changed fields. | ID | The ID of the work item |
onLoaded |
Fired after the data gets loaded in the work item form, when the user opens a work item, or when the user navigates to another work item in the triage view. | ID | The ID of the work item |
onReset |
Fired after the user undoes the changes to the work item. | ID | The ID of the work item |
onRefreshed |
Fired after the user refreshes the work item manually. | ID | The ID of the work item |
onSaved |
Fired after a work item is saved. For work items in a dialog, you should target the ms.vss-work-web.work-item-notifications type to ensure the event fires since once the dialog closes, this contribution type gets unloaded. For more information, see Listen for events. |
ID | The ID of the work item |
onUnloaded |
Fired before the user closes the dialog, or before the user moves to another work item in the triage view. | ID | The ID of the work item |
Add a page
A new page is rendered as a tab on the work item form. New pages appear next to the Details tab.
To add a page to the work item form, add a contribution to your extension manifest with type ms.vss-work-web.work-item-form-page targeting ms.vss-work-web.work-item-form:
"contributions": [
{
"id": "sample-work-item-form-page",
"type": "ms.vss-work-web.work-item-form-page",
"description": "Custom work item form page",
"targets": [
"ms.vss-work-web.work-item-form"
],
"properties": {
"name": "My Page",
"uri": "workItemPage.html"
}
}
]
Properties
| Property | Description |
|---|---|
name |
Text that appears on the tab page. |
uri |
URI to the HTML page loaded in the IFrame. |
JavaScript sample
See the JavaScript sample in the form group section. The name of the registered object should match the id of the contribution.
Events
| Event | Event description | Argument | Argument description |
|---|---|---|---|
onFieldChanged |
Fired after a field has changed. If the field change ran rules that updated other fields, all these changes are part of a single event. | ID | The ID of the work item |
changedFields |
Array with the reference name of all changed fields. | ID | The ID of the work item |
onLoaded |
Fired after the data gets loaded in the work item form, when the user opens a work item, or when the user navigates to another work item in the triage view. | ID | The ID of the work item |
onReset |
Fired after the user undoes the changes to the work item. | ID | The ID of the work item |
onRefreshed |
Fired after the user refreshes the work item manually. | ID | The ID of the work item |
onSaved |
Fired after a work item is saved. For work items in a dialog, you should target the ms.vss-work-web.work-item-notifications type to ensure the event fires since once the dialog closes, this contribution type gets unloaded. For more information, see Listen for events. |
ID | The ID of the work item |
onUnloaded |
Fired before the user closes the dialog, or before the user moves to another work item in the triage view. | ID | The ID of the work item |
Configure contributions
In Azure DevOps Services, group extensions appear at the end of the second column by default, and page contributions appear as the last tab. Control contributions aren't shown by default - users must manually add them to the form. In Azure DevOps Server, see Configure work item form extensions to show, hide, or move contributions.
Add menu action
To add an item to the work item toolbar, add this contribution to your extension manifest. The item appears in the vertical ellipsis (...) dropdown menu.
"contributions": [
{
"id": "sample-work-item-menu",
"type": "ms.vss-web.action",
"description": "Sample toolbar item which updates the title of a work item",
"targets": [
"ms.vss-work-web.work-item-context-menu"
],
"properties": {
"text": "Try me!",
"title": "Updates the title of the work item from the extension",
"toolbarText": "Try me!",
"icon": "images/show-properties.png",
"uri": "menu-workItemToolbarButton.html"
}
}
]
Properties
| Property | Description |
|---|---|
text |
Text that appears on the toolbar item. |
title |
Tooltip text that appears on the menu item. |
toolbarText |
Text that appears when the item is being hovered over. |
uri |
URI to a page that registers the toolbar action handler. |
icon |
URL to an icon that appears on the menu item. Relative URLs are resolved using baseUri. |
group |
Determines where the menu item appears, related to others. Toolbar items with the same group name are grouped and divided by a separator from the rest of the items. |
registeredObjectId |
(Optional) Name of the registered menu action handler. Defaults to the contribution ID. |
Listen for events
Observers listen to work item events without any UI on the form. Use observers to listen for the onSaved event, since observers live outside the form and aren't destroyed when the form dialog closes.
"contributions": [
{
"id": "sample-work-item-form-observer",
"type": "ms.vss-work-web.work-item-notifications",
"description": "Gets events about the current work item form for the 'Try Me!' toolbar button",
"targets": [
"ms.vss-work-web.work-item-form"
],
"properties": {
"uri": "myformobserver.html"
}
}
]
Properties
| Property | Description |
|---|---|
uri |
URI to a page that hosts the scripts listening to events. |
Events
| Event | Event description | Argument | Argument description |
|---|---|---|---|
onFieldChanged |
Fired after a field has changed. If the field change ran rules that updated other fields, all these changes are part of a single event. | ID | The ID of the work item |
changedFields |
Array with the reference name of all changed fields. | ID | The ID of the work item |
onLoaded |
Fired after the data gets loaded in the work item form, when the user opens a work item, or when the user navigates to another work item in the triage view. | ID | The ID of the work item |
onReset |
Fired after the user undoes the changes to the work item. | ID | The ID of the work item |
onRefreshed |
Fired after the user refreshes the work item manually. | ID | The ID of the work item |
onSaved |
Fired after a work item is saved. For work items in a dialog, you should target the ms.vss-work-web.work-item-notifications type to ensure the event fires since once the dialog closes, this contribution type gets unloaded. For more information, see Listen for events. |
ID | The ID of the work item |
onUnloaded |
Fired before the user closes the dialog, or before the user moves to another work item in the triage view. | ID | The ID of the work item |
JavaScript sample
The following example registers an observer by using the modern SDK:
import * as SDK from "azure-devops-extension-sdk";
SDK.init();
SDK.ready().then(() => {
SDK.register(SDK.getContributionId(), () => {
return {
onFieldChanged: (args) => {
// Handle field changes
},
onLoaded: (args) => {
// Handle work item loaded
},
onUnloaded: (args) => {
// Handle work item unloaded
},
onSaved: (args) => {
// Handle work item saved
},
onReset: (args) => {
// Handle work item reset (undo)
},
onRefreshed: (args) => {
// Handle work item refreshed
}
};
});
});
Compatibility notes
Action vs. action-provider
Use ms.vss-web.action-provider when dynamically loading menu items by using getMenuItems on the menu handler. Use ms.vss-web.action when your menu items are static and defined in the manifest.
Deprecated patterns
The following patterns are no longer supported:
require("VSS/Events/Document")- not supported with New Boards HubSDK.jsscript tag withusePlatformScripts: true- use the npm packageazure-devops-extension-sdkinstead