Webviews¶
Overview¶
The Webview API allows extensions to create fully customizable views within the VS Code extension. You can use Webviews to build complex user interfaces beyond the capabilities of VS Code's native APIs .
Think of a Webview as an iframe within VS Code that your extension controls. A Webview can render almost any HTML content in this frame and communicates with extensions using message passing.
Webview Lifecycle¶
Webview panels are owned by the extension that creates them. The following flowchart explains the lifecycle of a webview.
flowchart TD
A[Create webview] --> B[Maintain reference]
B --> C[Active state]
C --> D[Extension dispose webview]
C --> E[User closes webview]
E --> F[Webview is destroyed]
D --> F
F --> G[Clean up resources]
E -..-> I[Attempt to interact with closed webview]
I -..-> J[Throws exception]
Implementation steps¶
This guide outlines the steps to create and implement a Webview in the vscode-ansible extension. This might differ from the implementation for other extensions.
Step 1: Contribute a command¶
Define a command in the package.json for the extension. Implement this command
in the extension code to register and trigger the Webview.
"commands": [
{
"command": "myWebview.start",
"title": "Start a new webview",
"category": "Custom webviews"
}
]
Step 2: Create a Webview panel¶
In the extension code, use Use the vscode.window.createWebviewPanel function
to instantiate and render a Webview panel within the editor.
context.subscriptions.push(
vscode.commands.registerCommand("myWebview.start", () => {
// Create and show a new webview
const panel = vscode.window.createWebviewPanel(
"webview-id", // Identifies the type of the webview. Used internally
"Webview Title", // Title of the panel displayed to the user
vscode.ViewColumn.One, // Editor column to show the new webview panel in.
{}, // Webview options. More on these later.
);
}),
);
Step 3: Structure the code¶
To organize the code, create two separate files:
- Extension file (
<webview-name>Page.ts): This file hosts the webview. In this file you should: -
Define a class with methods to render, dispose, and manage the Webview lifecycle.
-
Create a method to return the HTML content for the Webview.
-
Link to the Webview file and access VSCode elements like commands and settings.
-
Access the vscode and workspace elements such as commands and settings and manipulate them.
-
Webview file: (
<webview-name>PageApp.ts): This file manages the Webview content. In this file you should: -
Interact with DOM elements within the HTML.
-
Add event listeners and manipulate HTML elements, excluding vscode and workspace elements.
Tip
You can set up communication between the extension and the webview. This is covered in the further section.
Step 4: Build and debug¶
Build the extension and run the
extension in debug mode using the configuration Launch extension. Make changes
in the code and reload the extension host window to see the live implementation.
Debugging the Webviews¶
VS Code is built with Electron and includes Chrome's built-in browser and DevTools. This setup allows debugging both VS Code and Webviews. Follow the steps below to debug a Webview in VS Code:
-
Compile and start by running your VS Code extension in debug mode (refer Step 5 of Implementation steps).
-
Navigate to and open the Webview you wish to debug within the editor.
-
Press
Ctrl + Shift + P(Windows/Linux) orCmd + Shift + P(Mac) to bring up the Command Palette. -
Search for the command
Open Webview Developer Toolsand select it.
After these steps are completed, an instance of DevTools will open in a separate window. You can use this instance to do the following:
-
Select and inspect the HTML elements within the Webview.
-
Tweak CSS styles directly to see live changes.
-
Add breakpoints and debug JavaScript code, similar to debugging a standard webpage.
Communication between the webview panel and the extension¶
sequenceDiagram
participant Extension
participant Webview
participant HTML
Webview->>Extension: Ready to get data
Extension->>Webview: Post data to webview
Webview->>HTML: Render HTML
Webview->>Extension: Send message to perform the action
Passing message from the extension context to the webview context¶
The extension can send data to its webviews using webview.postMessage(). This
method sends any JSON serializable data to the webview. The message is received
inside the webview through the standard message event.
extension context code:
// Send a message to our webview.
// You can send any JSON serializable data.
currentPanel.webview.postMessage({ command: "refactor" });
webview context code:
// Handle the message inside the webview
window.addEventListener("message", (event) => {
const message = event.data; // The JSON data our extension sent
switch (message.command) {
case "refactor":
count = Math.ceil(count * 0.5);
counter.textContent = count;
break;
}
});
Passing a message from the webview context to the extension context¶
Webviews can pass messages back to their extension. This is accomplished using
postMessage() on a special VS Code API object inside the webview. To access
the VS Code API object, call acquireVsCodeApi() inside the webview. This
function can only be invoked once per session. You must hang onto the instance
of the VS Code API returned by this method, and hand it out to any other
functions that need to use it.
webview context code:
// Access the vscode API object and post message
const vscode = acquireVsCodeApi();
vscode.postMessage({
command: "alert",
text: "Hello, world!",
});
extension context code:
// Handle messages from the webview
panel.webview.onDidReceiveMessage(
(message) => {
switch (message.command) {
case "alert":
vscode.window.showErrorMessage(message.text);
return;
}
},
undefined,
context.subscriptions,
);
Resources¶
- Local resources: The extension has already implemented some webviews. You can see them in the following locations:
-
extension context file: createAnsibleProjectPage.ts
-
webview context file: createAnsibleProjectPageApp.ts
-
External resources: The best explanation of implementing a webview is described by Microsoft. You can look at these: