This topic is for frontend developers. If the available DataV widgets and materials do not meet the requirements of your scenario, you can create your own custom widgets.
Development environment
Download and install Node.js from the official Node.js website. We recommend using a Node.js version that is 8.0.0 or later and earlier than 10.12.0. Versions outside this range are not supported. We also recommend using nvm to manage Node.js. For more information about the installation procedure, see Quick start for widget development.
If you installed Node.js on Windows but cannot find or use it, your environment variable is likely not configured correctly.
After the installation is complete, run the node -v command to check the Node.js version.
Create a widget package
Log on to the DataV console.
On the console page, click My Assets > My Widget Packages > New Widget Package Project.
Enter the English Name and Chinese Name for the widget package, and then click Create in the lower-right corner.
NoteThe English name of the widget package must be in the `CompanyName.PackageName` or `CompanyName-PackageName` format. The Chinese name can be customized.
After the widget package is created, its status is Under review. All widget packages are reviewed manually. If your widget package is not reviewed for an extended period or the review fails, contact a technical support engineer for assistance.
After the widget package is approved, run the following command to download the datav-cli command-line tool.
npm install datav-cli -gRun
datav --versionto check the version of the development tool.In the DataV console, locate your Username in the upper-right corner. Go to the My Widget Packages page and click Developer Access Token to copy the token. Then, run the
datav logincommand to log on.After you log on, run the
datav initcommand. Enter the Widget Name, Display Name, Widget Description, and Basic Text Generation Widget. After the widget is created, a widget folder is automatically generated in the current directory.Run the
datav runcommand to preview your widget locally.After you preview the widget, you can publish it in one of the following two ways:
Method 1: In the widget folder, run the
datav publishcommand. This method requires your username and developer access token. (Recommended)Method 2: In the widget folder, run the
datav packagecommand. A compressed package named `WidgetName-VersionNumber.tar.gz` is generated in the parent directory of the widget folder. Upload this package on the My Widget Packages page in the DataV console.
NoteAfter you run the
datav publishcommand, the packaging process runs on the server and may be queued. If the command indicates that the widget is published successfully but an error occurs when you pull the widget, the packaging process is likely still in the queue. In this case, wait a few moments, refresh your browser, and then retry.Open the widget in a development tool. The main configuration is performed in the `package.json` and `index.js` files. For information about the code settings in the `package.json` file, see the following example:
{ "name": "@aliyun-datav_design/datav-r", // Must be the same as the English name of the widget package. "version": "0.0.9", "dependencies": { "bcore": "0.0.18", "jquery": "2.1.4", "lodash": "4.6.1" }, "datav": { "cn_name": "datav-r", "icon": "", "protocol": 2, "type": [ "regular" ], "view": { "width": "400", "height": "600", "minWidth": "200", "minHeight": "100" }, "apis": { "source": { "handler": "render", "description": "API description", "fields": { "value": { "description": "Value description" } } } }, "config": { "size": { "name": "Font size", "type": "number", "default": 22, "range": [ 10, 100 ] }, "color": { "name": "Font color", "type": "color", "default": "#fff" },"path": { "type": "hidden", "default": "./resources/img.png" } }, "events": { "button-click": { "name": "On click", "description": "Description for the click event", "type": "string" } }, "publicHandler": { "setColor": { "name": "Change text color", "type": "object", "fields": { "color": { "name": "Text color", "description": "Change the text color", "type": "string | number", "default": "red" } } } }, "api_data": { "source": [ { "value": "Value test" } ] } } }After the widget is published, you can view it in a visualization application.
Widget structure
`index.js` is the main program entry point, and `package.json` is the configuration file.
The main methods in the `index.js` file are as follows. For more information about other methods and configuration standards, see index.js standards.
`init()`: Initializes the widget.
`render(array: data)`: The default rendering method. This method renders the widget based on the provided data.
`destroy()`: Destroys the widget. This method is called when the widget is removed.
The common field standards for `package.json` are as follows. For more information about other field configuration standards, see package.json standards.
Widget type, name, and style definitions.
Interaction event standards.
GUI field standards.
Data field standards.
Node-based programming action field standards.
Tutorial
For information about configuring the `package.json` file, see package.json standards:
{
"name": "@aliyun-datav_design/datav-r", // Must be the same as the English name of the widget package.
"version": "0.0.9",
"dependencies": {
"bcore": "0.0.18",
"jquery": "2.1.4",
"lodash": "4.6.1"
},
"datav": {
"cn_name": "datav-r",
"icon": "",
"protocol": 2,
"type": [
"regular"
],
"view": {
"width": "400",
"height": "600",
"minWidth": "200",
"minHeight": "100"
},
"apis": {
"source": {
"handler": "render",
"description": "API description",
"fields": {
"value": {
"description": "Value description"
}
}
}
},
"config": {
"size": {
"name": "Font size",
"type": "number",
"default": 22,
"range": [
10,
100
]
},
"color": {
"name": "Font color",
"type": "color",
"default": "#fff"
},"path": {
"type": "hidden",
"default": "./resources/img.png"
}
},
"events": {
"button-click": {
"name": "On click",
"description": "Description for the click event",
"type": "string"
}
},
"publicHandler": {
"setColor": {
"name": "Change text color",
"type": "object",
"fields": {
"color": {
"name": "Text color",
"description": "Change the text color",
"type": "string | number",
"default": "red"
}
}
}
},
"api_data": {
"source": [
{
"value": "Value test"
}
]
}
}
}
For more information about color configuration, see color.
For information about configuring the `index.js` file, see index.js standards:
var Event = require('bcore/event');
var $ = require('jquery');
var _ = require('lodash');
//var Chart = require('XXX');
/**
* Basic MaLiang class
*/
module.exports = Event.extend(function Base(container, config) {
this.config = {
theme: {}
}
this.container = $(container); // Container
this.apis = config.apis; // Hooks are required.
this._data = null; // Data
this.chart = null; // Chart
this.init(config);
}, {
/**
* Public initialization
*/
init: function (config) {
// 1. Initialize and merge configurations.
this.mergeConfig(config);
// 2. Refresh the layout. This is optional for widgets with sub-widgets.
this.updateLayout();
// 3. Instantiate sub-widgets.
//this.chart = new Chart(this.container[0], this.config);
// 4. Update the style if needed.
this.updateStyle(); this.container.append('<div class="button">1111111</div>')
this.button = this.container.find(".button");
// Default style (Do not reference a global CSS style sheet in the widget. Write the style directly in JavaScript.)
this.button.css({
color: "#fff",
cursor: "pointer",
});
},
/**
* Render
* @param data
* @param options Optional
* !!Note: If the second parameter supports config, the updateOptions method is not required.
*/
render: function (data, config) {
data = this.data(data);
var cfg = this.mergeConfig(config);
// Update the chart.
//this.chart.render(data, cfg);
// this.container.html(data[0].value)
// Update the style if needed.
this.updateStyle(); this.button.html(_.get(data, [0, "value"]));
// Click event (how to configure the callback ID)
var _this = this;
this.button.on("click", function () {
_this.emit("button-click", {"value": $(this).html()});
});
},
setColor: function(obj){
this.button.css({color: obj.color})
},
/**
*
* @param width
* @param height
*/
resize: function (width, height) {
this.updateLayout(width, height);
// Update the chart.
//this.chart.render({
// width: width,
// height: height
//})
},
/**
* Each widget can obtain colors from the theme to overwrite its own configured colors as needed.
* You can leave this empty for now.
*/
setColors: function () {
// For example
//var cfg = this.config;
//cfg.color = cfg.theme.series[0] || cfg.color;
},
/**
* Data. Sets and gets data.
* @param data
* @returns {*|number}
*/
data: function (data) {
if (data) {
this._data = data;
}
return this._data;
},
/**
* Merge configurations.
* Priority: config.colors > config.theme > this.config.theme > this.config.colors
* [Note] Configurations that contain arrays must be replaced.
* @param config
* @private
*/
mergeConfig: function (config) {
if (!config) {return this.config}
this.config.theme = _.defaultsDeep(config.theme || {}, this.config.theme);
this.setColors();
this.config = _.defaultsDeep(config || {}, this.config);
return this.config;
},
/**
* Update the layout.
* Optional.
*/
updateLayout: function () {},
/**
* Update the style.
* Implement changes here that cannot be controlled by sub-widgets.
*/
updateStyle: function () {
var cfg = this.config;
this.container.css({
'font-size': cfg.size + 'px',
'color': cfg.color || '#fff'
});
},
/**
* Update configurations.
* !!Note: If render supports the second parameter options, updateOptions is not required.
*/
//updateOptions: function (options) {},
/**
* Update certain configurations.
* For widgets that support incremental configuration updates.
*/
//updateXXX: function () {},
/**
* Destroy the widget.
*/
destroy: function(){console.log('Implement the destroy method')}
});
FAQ
How do I use CSS when developing a custom widget?
To prevent style conflicts between widgets in a visualization application, do not create separate Cascading Style Sheets (CSS) files. Instead, modify the DOM style using JavaScript in the main program.
How do I use HTML when developing a custom widget?
You can create HTML tags in the main program by importing a separate HTML file or using a string template.
How do I configure a callback ID when developing a custom widget?
In the `package.json` configuration file, define the events event name and parameters in the correct format under the
datavfield.In the `index.js` main program, use the following method to send the event name and data parameters.
this.emit(string:event_name,object: value)NoteThe
valueparameter must be an object.After you enable interaction on the widget interaction panel in the visualization application, other widgets can retrieve the callback data. In the configuration of a dynamic data source for another widget, you can reference the callback data using a colon (:) followed by the parameter name.
When developing a custom widget, how do I register a widget method in node-based programming?
In the `package.json` configuration file, define the publicHandler action name and parameters in the correct format under the
datavfield.In the `index.js` main program, implement the code logic for the corresponding action defined in the configuration file.
How do I log on to the development tool for custom widgets?
You can log on using a username and a token. The username is your Alibaba Cloud account name, which is displayed in the upper-right corner of the DataV console. The token is the Developer Access Token.
NoteTo obtain the developer access token, go to the DataV console homepage, choose My Assets > My Widget Packages, click Developer Access Token to copy it, and then paste it into the command line when prompted.
What do I do if publishing a custom widget fails?
Check whether the
namefield in the `package.json` configuration file is set to the English name of the approved widget package. This ensures that you have the required permissions to publish the widget. The correct format for thenamefield is @namespace/xxx. For more information about other solutions, see FAQ about custom widget development.
Video link
Video tutorial: Custom Widgets - Lesson 1.