The vSphere HTML Client SDK offers a set of JavaScript APIs which facilitate the building of HTML Client-only plugins, fully compatible with the HTML-based vSphere Client.
These JavaScript APIs are documented here as if they have TypeScript signatures, but they run as pure JavaScript, and all complex types are plain old Javascript objects.
The JavaScript APIs may be used by the plugin to communicate with the HTML Client and to execute a number of operations. Each plugin will have access to the JavaScript APIs within its own iframe which eliminates the possibility of plugin conflicts. Please refer to the Plug-in Architecture Diagram in the online vSphere Client SDK documentation.
WARNING: Do not access the window.parent (the Client window), as this is unsupported and if your plugin relies on this it might break in a future release of the vSphere Client.
The JavaScript APIs are organized in several domains depending on their functionality. This improves readability and communicates clearly the API functionality scope:
For the most part frontend APIs for remote plugins are the same as for local plugins.
In order to isolate plugins a new asynchronous way for communicating with the parent window is in place, namely the plugin communicates with the vSphere Client with a window.postMessage mechanism.
A Client Library abstracts plugin writers from this new mechanism. It exposes the frontend APIs in a standard manner, and hides the complexity associated with asynchronious programming.
The Client Library is not bundled with plugins and is dynamically loaded from a fixed location. This approach allows for transparent bug fixes and new APIs to be delivered in future vSphere Client releases.
WARNING: Do not reverse engineer the Client Library and do not use anything not provided by the APIs. Doing this might break your plugin in future vSphere Client releases.
The JavaScript APIs can be accessed by including the "/api/ui/htmlClientSdk.js" source. For example: <script src="/api/ui/htmlClientSdk.js"/>.
Once the htmlClientSdk.js source is included, the htmlClientSdk object is created in the iframe's window which has two functions:
The client application APIs are related to the HTML Client application. The client application APIs can be accessed with the
htmlClientSdk.app.{API}
| APIs | Description | Example usage |
|---|---|---|
| formatDateTime(instant: number, options?: PluginDateTimeFormatOptions) => string |
Formats the specified date-time instant using the provided options. Returns a string which represents the formatted date. The instant should be a Unix Time Stamp, an integer value that is the number of milliseconds since 1 January 1970 UTC. PluginDateTimeFormatOptions type is defined as follows: interface PluginDateTimeFormatOptions { format?: "DATE" | "TIME" | "DATE_AND_TIME"; } Where:
|
htmlClientSdk.app.formatDateTime(1557735887313); Returns: "05/13/2019, 11:24:47 AM" htmlClientSdk.app.formatDateTime(1557735887313, {format: "DATE"}); Returns: "05/13/2019" htmlClientSdk.app.formatDateTime(1557735887313, {format: "TIME"}); Returns: "11:24:47 AM" htmlClientSdk.app.formatDateTime(1557735887313, {format: "DATE_AND_TIME"}); Returns: "05/13/2019, 11:24:47 AM" |
| getApiEndpoints() => ApiEndpoints | Returns an object containing the base locations of vSphere Client plugin related APIs.
The returned object is of type ApiEndpoints, where: interface ApiEndpoints { uiApiEndpoint: UiApiEndpoint; } interface UiApiEndpoint { origin: string; pathname: string; queryParams: QueryParam[]; fullUrl: string; } Where:
interface QueryParam { name: string; value: string; } |
htmlClientSdk.app.getApiEndpoints();
for example:
|
| getClientInfo() => ClientInfo | Returns information about the current vSphere Client, such as "version", "type" etc.
interface ClientInfo { type?: string; version?: string; } Where:
|
htmlClientSdk.app.getClientInfo();
for example: {type: "HTML", version: "6.5.1"} |
| getClientLocale() => string | Returns the current locale of the vSphere Client. |
htmlClientSdk.app.getClientLocale();
for example: "de-DE" |
| getContextObjects() => any[] |
Returns current context objects:
|
htmlClientSdk.app.getContextObjects();
for example: [ { id: "urn:vmomi:Datacenter:datacenter-1" } ] |
| getNavigationData() => any | Retrieves the navigation data passed to the current view by the navigateTo() API.
|
If the following is called: htmlClientSdk.app.navigateTo({ targetViewId: "acme-plugin-monitor-view", objectId: "urn:vmomi:Datacenter:datacenter-1", customData: {name: "test", filter: true} }); Then, any call to: htmlClientSdk.app.getNavigationData(); will return: {name: "test", filter: true} |
| getPluginBackendInfo(callback: (backendInfo: PluginBackendInfo | null) => void) => void | Retrieves the plugin backend info for the current remote plugin instance. In case of an exception in the backend call, the callback's parameter value (backendInfo) will be null.
The backendInfo object is of the following type: interface PluginBackendInfo { // a flat list of all registered global plugin backend servers for the instance across all vCenter Server registrations allPluginBackendServers: PluginBackendServerInfo[]; // a map of registered global plugin backend servers for the instance, per vCenter Server GUID backendServersPerVc: { [vcGuid: string]: PluginBackendServerInfo[] }; // a map of registered per object plugin backend servers for the instance, per objectId backendServersPerVcObject: { [objectId: string]: PluginBackendServerInfo[] }; } interface PluginBackendServerInfo { proxiedBaseUrl: string; type: string; } Where:
|
Consider a remote plugin instance registration with two vCenters Servers - vCenter1 with guid vc-guid-1 and vCenter2 with guid vc-guid-2. We call such such registrations "vCenter-global".
Along with the two vCenter-global registrations, consider a registration of the plugin instance with a Cluster object with value domain-c9 such that the Cluster object is part of the vCenter1 vCenter Server. We call such registrations "per-object registrations"
Let the vCenter-global plugin instance registration in vCenter1's Extension Manager contain two ServerInfo objects, such that:
htmlClientSdk.app.getPluginBackendInfo( (backendInfo) => { console.log(backendInfo); }) would yield a result similar to: {allPluginBackendServers: [ {proxiedBaseUrl: "/plugins/remote~1.0~8/10.30.198.150-8443", type: "AUX_SERVER_1"}, {proxiedBaseUrl: "/plugins/remote~1.0~8/10.30.198.149-5432", type: "COMMON_SERVER"}, {proxiedBaseUrl: "/plugins/remote~1.0~8/10.30.198.151-8443", type: "AUX_SERVER_2"}, {proxiedBaseUrl: "/plugins/remote~1.0~8/10.40.0.0-8443", type: "AUX_SERVER_3"} ], backendServersPerVc: { vc-guid-1: [ {proxiedBaseUrl: "/plugins/remote~1.0~8/10.30.198.150-8443", type: "AUX_SERVER_1"}, {proxiedBaseUrl: "/plugins/remote~1.0~8/10.30.198.149-5432", type: "COMMON_SERVER"} ], vc-guid-2: [ {proxiedBaseUrl: "/plugins/remote~1.0~8/10.30.198.151-8443", type: "AUX_SERVER_2"}, {proxiedBaseUrl: "/plugins/remote~1.0~8/10.30.198.149-5432", type: "COMMON_SERVER"} ] }, backendServersPerVcObject:{ 'urn:vmomi:ClusterComputeResource:domain-c9:vc-guid-1': [ {proxiedBaseUrl: "/plugins/remote~1.0~8/10.40.0.0-8443", type: "AUX_SERVER_3"} ], } } |
| getRemotePluginNavigationMap(targetPluginId: string, callback: ((navigationInfo: RemotePluginNavigationMap | null) => void)) => void |
Retrieves the navigation IDs of the views of the target remote plugin per vCenter Server and per inventory object.
The result contains the navigation IDs of the views that are marked as public within the manifest file of the target plugin.
If the target plugin ID is the same as the one requesting the views then non-public entries would be returned as well.
The result will contain information about all vCenter Servers and all vCenter Server objects with which an enabled
version of the target remote plugin is registered.
Parameters:
RemotePluginNavigationMap type is defined as follows: interface RemotePluginNavigationMap { // A map of vCenter Server GUID to the relevant remote plugin navigation information about that vCenter Server. navigationInfoByVcGuid: { [vcGuid: string]: RemotePluginVcNavigationInfo }; // A map of vCenter Server GUID to a list of relevant remote plugin navigation information and their associated inventory objects. navigationInfoByVcObject: { [vcGuid: string]: VcObjectsRemotePluginNavigationInfo[] }; } interface RemotePluginVcNavigationInfo { // The remote plugin version registered with the particular vCenter Server. pluginVersion: string; // The particular remote plugin version views' navigation IDs. viewsIds: string[]; } interface VcObjectsRemotePluginNavigationInfo { // The remote plugin version registered with the particular vCenter Server. info: RemotePluginVcNavigationInfo; // The inventory objects for which the remote plugin navigation info is valid. vcObjects: VcObjectInfo[]; } interface VcObjectInfo { // The type of the inventory object, e.g. 'ClusterComputeResource', 'HostSystem', etc. type: string; // The local ID of the object in respect to the vCenter Server, e.g. 'host-14'. value: sting; } |
Consider that a remote plugin with ID com.acme.remote
has a single registration within the environment. The registration is done
on vCenter with GUID vc-guid-0 for plugin instance with version 1.0.0.0.
Also consider that the plugin has a single public view within Host -> Monitor with navigationId mon.
Then the following API invocation: htmlClientSdk.app.getRemotePluginNavigationMap("com.acme.remote", function(map) { console.log(map); }); would yield the following result: { navigationInfoByVcGuid: { vc-guid-0: { pluginVersion: "1.0.0.0", viewsIds: ["mon"] } }, navigationInfoByVcObject: { vc-guid-0: [ { info: { pluginVersion: "1.0.0.0", viewsIds: ["mon"] }, vcObjects: [ { type: "vCenter", value: "vc-guid-0" } ] } ] } } |
| getSessionInfo(callback: (info: SessionInfo | null) => void) => void | Retrieves information about the current session. In case of an exception in the backend call, the callback's parameter value for sessionInfo is null.
The sessionInfo object has the following type: interface SessionInfo { sessionToken: string; nodeId: string; } Where:
|
htmlClientSdk.app.getSessionInfo(
(sessionInfo) => { console.log(sessionInfo); }) for example:
{
|
| getTheme() => PluginTheme |
Returns information about the theme the plugin should use. The returned
PluginTheme type is defined as follows:
interface PluginTheme { name: "light" | "dark" } |
htmlClientSdk.app.getTheme();
for example: { name: "dark" } |
| refreshPluginItemsState() => void |
Refreshes the cached plug-in's data that is related for the API
initiator.
For example: Plugin A introduces a view that is dynamically filtered based on a property value of some object. If the property value is changed by the plug-in using the public vSphere APIs, then the plug-in needs to call this API to signal the UI to re-evaluate the state of the initiator's plug-in related items. |
htmlClientSdk.app.refreshPluginItemsState(); |
| navigateTo(configObj: NavigationOptions) => void | Navigates to a specified view with an optional custom data which will be passed to the view.
The only valid values for the targetViewId are navigation IDs
defined by the plugin itself.
This means that the navigation to a cluster monitor view will not work if the view is not defined in the plugin.json of the plugin.
If just objectId is passed, then the default object view will be displayed.
The configuration object should contain the following information: interface NavigationOptions { targetViewId?: string; objectId?: string; customData?: any; } Where:
Note: When navigating to a global view, the objectId property should be skipped. |
htmlClientSdk.app.navigateTo({
targetViewId: "acme-plugin-monitor-view", objectId: "urn:vmomi:Datacenter:datacenter-1", customData: {name: "test", filter: true} }); |
| navigateToClientView(configObj: ClientViewNavigationOptions) => void | Navigates to a specified client view.
The configuration object should contain the following information: interface ClientViewNavigationOptions { targetViewId?: string; objectId?: string; } Where:
Note: When navigating to a global view, the objectId property should be skipped. |
htmlClientSdk.app.navigateToClientView({
targetViewId: "administration.ceip" }); |
| navigateToRemotePluginView(configObj: RemotePluginViewNavigationOptions) => void | Navigates to the specified view defined by a remote plugin with an optional custom data which will be passed to the view.
The valid values for the targetViewId parameter are the ones returned by the
htmlClientSdk.app.getRemotePluginNavigationMap() call for the given plugin.
The configuration object should contain the following information: interface RemotePluginViewNavigationOptions { pluginId: string; targetViewId: string; vcGuid: string; objectId?: string; customData?: any; } Where:
Note: When navigating to a global view, the objectId property should be skipped. |
htmlClientSdk.app.navigateToRemotePluginView({
pluginId: "acme-plugin", targetViewId: "acme-plugin-monitor-view", vcGuid: "vc-guid-0", objectId: "urn:vmomi:Datacenter:datacenter-1:vc-guid-0", customData: {name: "test", filter: true} }); |
The event APIs provide means for plugins to subscribe and respond to events. These APIs can be accessed via htmlClientSdk.event.{API}
| API | Description | Example usage |
|---|---|---|
| onDateTimeFormatChanged(callback: () => void) => void | Subscribes to date-time format change events. When the date-time format changes, the provided callback function will be invoked without arguments. |
function onTimeFormatPreferencesChange() { alert("The time format preferences have changed."); } htmlClientSdk.event.onDateTimeFormatChanged(onTimeFormatPreferencesChange); |
| onGlobalRefresh(callback: () => void) => void | Subscribes to a global refresh event and when such an event occurs, the callback function will be executed. |
function updateData() {
alert("Data is updated after a global refresh."); } htmlClientSdk.event.onGlobalRefresh(updateData); |
| onThemeChanged((theme: PluginTheme) => void) => void |
Subscribes for plugin theme changed events. When such an event occurs,
the callback argument function will be
invoked with a single argument - the new plugin theme in the form of
PluginTheme object.
The PluginTheme type is defined as follows: interface PluginTheme { name: "light" | "dark"; } |
function showCurrentThemeName(theme) { alert(theme.name); } htmlClientSdk.event.onThemeChanged(showCurrentThemeName); |
The modal APIs are used to perform various actions for a modal dialog such as open, close and configure. The modal APIs can be accessed with the htmlClientSdk.modal.{API}
| API | Description | Example usage |
|---|---|---|
| close(data?: any) => void | Closes the already opened modal. The modal is the one corresponding to the iframe from which this API was called from.
If data has been provided it will be passed to the onClose callback function if such was specified in the parameter of the modal.open API. |
var modalId = 2;
htmlClientSdk.modal.close(modalId); |
| getCustomData() => any | Returns the custom data that was provided upon opening the modal through customData property or null if the customData property was not set. |
htmlClientSdk.modal.getCustomData();
for example: {idsRange: [1, 9]} |
| getSharedModalsMap(targetPluginId: string, callback: ((sharedModalsMap: SharedModalsMap | null) => void)) => void |
Retrieves the IDs of the modals shared by a remote plugin per vCenter Server and per inventory object.
The result contains the IDs of the shared modals marked as public within the manifest file of the target plugin.
If the target plugin ID is the same as the one requesting the shared modals then non-public entries would be returned as well.
The result will contain information about all vCenter Servers and all vCenter Server objects with which an enabled
version of the target remote plugin is registered.
Parameters:
SharedModalsMap type is defined as follows: interface SharedModalsMap { // A map of vCenter Server GUID to information about the shared modals of the remote plugin relevant to that vCenter Server. sharedModalsInfoByVcGuid: { [vcGuid: string]: VcSharedModalsInfo }; // A map of vCenter Server GUID to information about the shared modals of the remote plugin relevant to each set of inventory objects which the remote plugin is registered. sharedModalsInfoByVcObjects: { [vcGuid: string]: VcObjectsSharedModalsInfo[] }; } interface VcSharedModalsInfo { // The remote plugin version registered with the given vCenter Server. pluginVersion: string; // The set of IDs of the shared modals exposed by the plugin. sharedModalsIds: string[]; } interface VcObjectsSharedModalsInfo { // The set of inventory objects. vcObjects: VcObjectInfo[]; // The remote plugin version registered with the set of inventory objects. pluginVersion: string; // The set of IDs of the shared modals exposed by the plugin. sharedModalsIds: string[]; } interface VcObjectInfo { // The type of the inventory object, e.g. 'ClusterComputeResource', 'HostSystem', etc. type: string; // The local ID of the object in respect to the vCenter Server, e.g. 'host-14'. value: sting; } |
Consider that a remote plugin with ID com.acme.remote
has a single registration within the environment. The registration is done
on vCenter with GUID vc-guid-0 for plugin instance with version 1.0.0.0.
Also consider that the plugin has a single public shared modal with id shared-modal.
Then the following API invocation: htmlClientSdk.modal.getSharedModalsMap("com.acme.remote", function(map) { console.log(map); }); would yield the following result: { sharedModalsInfoByVcGuid: { vc-guid-0: { pluginVersion: "1.0.0.0", sharedModalsIds: ["shared-modal"] } }, sharedModalsInfoByVcObjects: { vc-guid-0: [ { vcObjects: [ { type: "vCenter", value: "vc-guid-0" } ], pluginVersion: "1.0.0.0", sharedModalsIds: ["shared-modal"] } ] } } |
| open(configObj: ModalConfig) => void | Opens a modal dialog and accepts for parameter a configuration object, which contains:
interface ModalConfig { url: string; title?: string; accessibilityTitle?: string; size?: { width: number, height: number }; closable?: boolean; onClosed?: (result?: any) => void; contextObjects?: any[]; customData?: any; sanitizeData?: boolean; } Where:
|
var config = { url: "resources/editDatacenter.html", title: "Edit Datacenter", accessibilityTitle: "Edit Datacenter", size: { width: 490, height: 240 }, onClosed: function(id) { alert("Modal " + id + " closed."); }, contextObjects: [{ id: "urn:vmomi:Datacenter:datacenter-1" }, { id: "urn:vmomi:Datacenter:datacenter-2" }], customData: {idsRange: [1, 9]} }; htmlClientSdk.modal.open(config); |
| openConfirmationModal(configObj: ConfirmationModalConfig) => void | Opens a simplified modal dialog dedicated to showing confirmation messages. The API offers:
interface ConfirmationModalConfig { content: string; buttons: ModalButton[]; size?: ModalSize; alertLevel?: AlertLevel; title?: string; accessibilityTitle?: string; secondaryTitle?: string; closable?: boolean; onClosed?: () => void; } interface ModalSize { width: number; } interface ModalButton { label: string; type?: ButtonType; style?: ButtonStyle; callback?: () => void; } enum ButtonType { PRIMARY = "PRIMARY", SECONDARY = "SECONDARY" } enum ButtonStyle { SUCCESS = "SUCCESS", INFO = "INFO", WARNING = "WARNING", DANGER = "DANGER" } enum AlertLevel { SUCCESS = "SUCCESS", INFO = "INFO", WARNING = "WARNING", DANGER = "DANGER" } Where:
|
var confirmationModalConfig = { content: "Deleting a chassis can cause failures in your environment?", size: { width: 490 }, alertLevel: "DANGER", title: "Delete chassis.", accessibilityTitle: "Delete chassis. Chassis-1", secondaryTitle: "Chassis-1", buttons: [{ label: "DELETE", callback: () => {//some delete callback actions} }, label: "CANCEL", callback: () => {//some cancel callback actions} }], closable: false, onClosed: function() {//Default onClosed handler. Invoked on ESC / X button press} }; htmlClientSdk.modal.openConfirmationModal(confirmationModalConfig); |
| openSharedModal(configObj: SharedModalConfig) => void | Opens a modal shared by a remote plugin. The valid values for the configObj.sharedModalId parameter are the ones returned by the
htmlClientSdk.modal.getSharedModalsMap() call for the given plugin.
The configuration object has the following signature: interface SharedModalConfig { // The ID of the remote plugin that defines the shared modal. pluginId: string; // The ID of the shared modal. sharedModalId: string; // The GUID of the vCenter with which the target remote plugin instance is registered. vcGuid: string; // The ID of the object with which the target remote plugin instance is registered. Used when the remote plugin is registered with specific objects. This object is not passed to the modal and cannot be read by it, the object is only used to determine the remote plugin instance through which to open the modal. objectId?: string; // A callback to be invoked when the dialog is closed. The callback is invoked with a single argument, the result returned by modal if any. onClosed?: (result?: any) => void; // An optional field to store an array of context objects that can be passed to the modal when it is opened. The context objects can be retrieved by the modal using the API htmlClientSdk.app.getContextObjects(). contextObjects?: any[]; // An optional additional data that can be passed to the modal when it is opened. customData?: any; // Specifies whether the provided modal configuration data should be sanitized (serialized/deserialized) when sending. (default=true) sanitizeData?: boolean; Note: The vSphere Client SDK JS APIs for remote plugins utilize window.postMessage() API. This API uses the Structured Clone Algorithm which has certain limitations. Therefore, the modal API is using JSON.stringify() and JSON.parse() to serialize/deserialize the modal configuration object. This has some side effects, such as removing object's functions, treating Date objects as strings etc. In addition, JSON.stringify() does not support cyclic objects i.e. objects that have cyclic references to themselves. For more information, see: JSON.stringify() documentation. In case such objects need to be passed, sanitizeData: false should be specified in the modal configuration object. } Note: The onClosed callback result argument is populated only in case the modal closed itself through the API htmlClientSdk.modal.close() and passed a result argument to the API. In case of an asynchronous error while opening the modal the onClosed callback will be invoked with undefined as result argument. |
htmlClientSdk.modal.openSharedModal({
pluginId: "com.acme.remote", sharedModalId: "shared-modal", vcGuid: "vc-guid-0", onClosed: function(result) { console.log("Modal closed with result", result); }, contextObjects: [{ id: "urn:vmomi:Datacenter:datacenter-1:0d497fd2-e54b-4376-8ae2-a4a12981100d" }], customData: { preselectedHosts: ["urn:vmomi:HostSystem:host-1:0d497fd2-e54b-4376-8ae2-a4a12981100d"] } }); |
| setOptions(configObj: DynamicModalConfig) => void | Changes the configuration of the modal with properties specified in the parameter object.
The configObj type is defined as follows: interface DynamicModalConfig { title?: string; accessibilityTitle?: string; height?: number; } Where:
|
htmlClientSdk.modal.setOptions({
title: "New Title", accessibilityTitle: "New Accessibility Title", height: 450 }); |