You can access extensions to customize the HTML JavaScript Dashboard. The extension is an independent JavaScript module/class that adds specific functionality to the control. For example, the DashboardExportExtension enables users to export the dashboard’s data, the DashboardParameterDialogExtension adds dashboard parameters, and the ToolboxExtension allows you to customize the Toolbox.
This topic explains how to access extensions, customize them, or create new extensions.
Get Underlying DashboardControl
You can customize the Web Dashboard before the underlying control is rendered. For this, you need to get access to the DashboardControl instance. Use the BeforeRender event to configure the underlying part for wrappers (Web Forms, MVC, and ASP.NET Core controls). Refer to the following topics on how to obtain the DashboardControl:
For the HTML JavaScript control, configure the control before you call the render method:
window.onload = function () {
var dashboardControl = new DevExpress.Dashboard.DashboardControl(document.getElementById("web-dashboard"), {
// Here you configure the control's options.
});
// Here you can customize a control.
dashboardControl.render();
}
Note
The dashboardControl variable in the examples below is the obtained DashboardControl instance.
Add or Remove Existing Extensions
To access all the enabled extensions, use the DashboardControl.extensions property that returns an array of objects. Each object implements the IExtension interface.
For example, the ViewerApiExtension class is used to customize the Web Dashboard’s visual components. The image below shows a custom button in the dashboard title:
You can modify the following visual components with the ViewerApiExtension’s events:
- Dashboard menu
- Toolbox
- Toolbar
- Dashboard title
- Dashboard item caption
- Dashboard item menu
Each extension exposes the IExtension.name property which returns an extension’s unique name. Use this name to access the extension.
To disable an extension, pass its name (IExtension.name) to the DashboardControl.unregisterExtension method. The code below shows how to disable the Web Dashboard’s export functionality:
function onBeforeRender(sender) {
// ...
dashboardControl.unregisterExtension("dashboard-export");
}
Note that some extensions (for instance, DashboardPanelExtension) are disabled. The code below shows how to use the DashboardControl.registerExtension method to enable the Dashboard Panel:
function onBeforeRender(sender) {
// ...
dashboardControl.registerExtension(new DevExpress.Dashboard.DashboardPanelExtension(dashboardControl));
}
Customize Existing Extension
To configure the registered extension, use the DashboardControl.findExtension method to obtain its instance and pass the IExtension.name property value as a method parameter.
The code sample below demonstrates how to use the ToolboxExtension.removeMenuItem to remove the New… command from the dashboard menu (ToolboxExtension):
function onBeforeRender(sender) {
// ...
var toolboxExtension = dashboardControl.findExtension("toolbox");
toolboxExtension.removeMenuItem("create-dashboard");
}
Example: How to Add Save As and Delete Functionality to the ASP.NET Core Dashboard
This example demonstrates how to add the “Save As” and “Delete” menu items to the Web Dashboard’s UI by implementing the corresponding custom extensions:
- The “Save As” menu item allows end-users to save the current dashboard with a new name.
- The “Delete” menu item deletes the opened dashboard from the dashboard storage.
The image below shows the result of the extensions implementation.
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Linq;
using System.Threading.Tasks;
using Microsoft.AspNetCore.Mvc;
using NetCoreWebApplication.Models;
using NetCoreWebApplication.Storages;
namespace NetCoreWebApplication.Controllers
{
public class HomeController : Controller
{
public IActionResult Index()
{
return View();
}
public IActionResult About()
{
ViewData["Message"] = "Your application description page.";
return View();
}
public IActionResult Contact()
{
ViewData["Message"] = "Your contact page.";
return View();
}
public IActionResult Error()
{
return View(new ErrorViewModel { RequestId = Activity.Current?.Id ?? HttpContext.TraceIdentifier });
}
public IActionResult DeleteDashboard(string DashboardID) {
CustomDashboardFileStorage newDashboardStorage = new CustomDashboardFileStorage("App_Data\\Dashboards");
newDashboardStorage.DeleteDashboard(DashboardID);
return new EmptyResult();
}
}
}
using DevExpress.DashboardWeb;
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Threading.Tasks;
namespace NetCoreWebApplication.Storages
{
public class CustomDashboardFileStorage : DashboardFileStorage {
public CustomDashboardFileStorage(string workingDirectory)
: base(workingDirectory) {
}
public void DeleteDashboard(string dashboardID) {
var dashboardPath = base.ResolveFileName(dashboardID);
if (File.Exists(dashboardPath))
File.Delete(dashboardPath);
}
}
}
@{
Layout = null;
}
<!-- Add the following namespace usages: -->
@using DevExpress.AspNetCore
@using DevExpress.DashboardWeb
<!DOCTYPE html>
<html lang="en">
<head>
<link href="css/site.min.css" rel="stylesheet" />
<script type="text/javascript" src="js/site.min.js"></script>
<script type="text/javascript" src="js/SaveAsExtension.js"></script>
<script type="text/javascript" src="js/DeleteExtension.js"></script>
<!-- Defines the "Save As" extension template. -->
<script type="text/html" id="dx-save-as-form">
<div>Dashboard Name:</div>
<div style="margin: 10px 0" data-bind="dxTextBox: { value: newName }"></div>
<div data-bind="dxButton: { text: 'Save', onClick: saveAs }"></div>
</script>
<script type="text/javascript">
function onBeforeRender(sender) {
var dashboardControl = sender;
dashboardControl.registerExtension(new SaveAsDashboardExtension(dashboardControl));
dashboardControl.registerExtension(new DeleteDashboardExtension(dashboardControl));
}
</script>
</head>
<body>
<!-- Add the Web Dashboard with “clientDashboardDesigner1” name to a View, specify its size, and set the Working Mode to Designer. -->
<div style="position: absolute; left:0;top:0;right:0;bottom:0;">
@(Html.DevExpress().Dashboard("clientDashboardDesigner1")
.WorkingMode(WorkingMode.Designer)
.Width("100%")
.Height("100%")
.OnBeforeRender("onBeforeRender")
)
</div>
</body>
</html>
using Microsoft.AspNetCore.Builder;
using Microsoft.AspNetCore.Hosting;
using Microsoft.Extensions.Configuration;
using Microsoft.Extensions.DependencyInjection;
using DevExpress.DashboardAspNetCore;
using DevExpress.DashboardWeb;
using DevExpress.AspNetCore;
using DevExpress.DashboardCommon;
using System.Data;
using System;
using NetCoreWebApplication.Storages;
namespace NetCoreWebApplication {
public class Startup {
public Startup(IConfiguration configuration) {
Configuration = configuration;
}
public IConfiguration Configuration { get; }
public void ConfigureServices(IServiceCollection services) {
// Add a DashboardController class descendant with a specified dashboard storage
// and a connection string provider.
services
.AddDevExpressControls()
.AddMvc()
.AddDefaultDashboardController(configurator => {
configurator.SetDashboardStorage(new CustomDashboardFileStorage("App_Data\\Dashboards"));
configurator.SetConnectionStringsProvider(new DashboardConnectionStringsProvider(Configuration));
});
}
public void Configure(IApplicationBuilder app, IHostingEnvironment env) {
if (env.IsDevelopment()) {
app.UseDeveloperExceptionPage();
} else {
app.UseExceptionHandler("/Home/Error");
}
app.UseStaticFiles();
// Register the DevExpress middleware.
app.UseDevExpressControls();
app.UseMvc(routes => {
// Map dashboard routes.
routes.MapDashboardRoute();
routes.MapRoute(
name: "default",
template: "{controller=Home}/{action=Index}/{id?}");
});
}
}
}
function SaveAsDashboardExtension(dashboardControl) {
this._dashboardControl = dashboardControl;
this._menuItem = {
id: "dashboard-save-as",
title: "Save As...",
template: "dx-save-as-form",
selected: ko.observable(true),
disabled: ko.computed(function () { return !dashboardControl.dashboard(); }),
index: 112,
data: this
};
this.newName = ko.observable("New Dashboard Name");
}
SaveAsDashboardExtension.prototype.saveAs = function () {
if (this.isExtensionAvailable()) {
this._toolbox.menuVisible(false);
this._newDashboardExtension.performCreateDashboard(this.newName(), this._dashboardControl.dashboard().getJSON());
}
};
SaveAsDashboardExtension.prototype.isExtensionAvailable = function () {
return this._toolbox !== undefined && this._newDashboardExtension !== undefined;
}
SaveAsDashboardExtension.prototype.start = function () {
this._toolbox = this._dashboardControl.findExtension("toolbox");
this._newDashboardExtension = this._dashboardControl.findExtension("create-dashboard");
if (this.isExtensionAvailable())
this._toolbox.menuItems.push(this._menuItem);
};
SaveAsDashboardExtension.prototype.stop = function () {
if (this.isExtensionAvailable())
this._toolbox.menuItems.remove(this._menuItem);
}
function DeleteDashboardExtension(dashboardControl) {
this._dashboardControl = dashboardControl;
this.name = "dxdde-delete-dashboard";
this._menuItem = {
id: this.name,
title: "Delete",
click: this.deleteDashboard.bind(this),
selected: ko.observable(false),
disabled: ko.computed(function () { return !this._dashboardControl.dashboard(); }, this),
index: 113,
hasSeparator: true,
data: this
};
}
DeleteDashboardExtension.prototype.deleteDashboard = function () {
if (this._toolbox) {
if (confirm("Delete this Dashboard?")) {
var dashboardid = this._dashboardControl.dashboardContainer().id;
this._toolbox.menuVisible(false);
$.ajax({
url: 'Home/DeleteDashboard',
data: { DashboardID: dashboardid },
type: 'POST',
success: (function() { this._dashboardControl.unloadDashboard(); }).bind(this)
});
}
}
}
DeleteDashboardExtension.prototype.start = function () {
this._toolbox = this._dashboardControl.findExtension('toolbox');
this._toolbox && this._toolbox.menuItems.push(this._menuItem);
};
DeleteDashboardExtension.prototype.stop = function () {
this._toolbox && this._toolbox.menuItems.remove(this._menuItem);
};
See Also