-
-
Notifications
You must be signed in to change notification settings - Fork 86
Integrating Chartkick
Here is an example of how to use Chartkick with the default uibuilder v2 installation to add a multiple charts using both Chart.js and Google Charts.
ChartKick is a library that simplifies the creation of charts using one or more chart libraries: Chart.js, Google Charts, and Highcharts.
Add an instance of uibuilder to your flows and replace the index.html and index.js files with the code below.
I'm loading the chart libraries using a CDN here, the next step would be to install the two packages using uibuilder's npm interface.
The example flow sends an array of [timestamp,random-number]
to the app every 10 seconds which is used to update the area chart with up to 1000 entries (after which the oldest entries are dropped off when a new msg arrives).
Note that the following flow also includes 2 comment nodes containing the html and javascript.
[{"id":"df81cc9e.a9171","type":"inject","z":"18cb249f.38bafb","name":"repeat every 10s","topic":"","payload":"","payloadType":"date","repeat":"10","crontab":"","once":false,"onceDelay":0.1,"x":130,"y":80,"wires":[["6ca36476.d0597c"]]},{"id":"76678044.5aaeb","type":"debug","z":"18cb249f.38bafb","name":"","active":true,"tosidebar":true,"console":false,"tostatus":false,"complete":"false","x":650,"y":60,"wires":[]},{"id":"bd9b5761.fb4918","type":"debug","z":"18cb249f.38bafb","name":"","active":true,"tosidebar":true,"console":false,"tostatus":false,"complete":"true","targetType":"full","x":630,"y":100,"wires":[]},{"id":"b18a50dd.f7e5c","type":"uibuilder","z":"18cb249f.38bafb","name":"","topic":"","url":"chart","fwdInMessages":false,"allowScripts":false,"allowStyles":false,"copyIndex":true,"showfolder":false,"x":490,"y":80,"wires":[["76678044.5aaeb"],["bd9b5761.fb4918"]]},{"id":"6ca36476.d0597c","type":"change","z":"18cb249f.38bafb","name":"","rules":[{"t":"set","p":"payload","pt":"msg","to":"[\t payload, ($random()*10)\t]\t","tot":"jsonata"}],"action":"","property":"","from":"","to":"","reg":false,"x":320,"y":80,"wires":[["b18a50dd.f7e5c"]]},{"id":"3ebfbce9.6ccd84","type":"comment","z":"18cb249f.38bafb","name":"html","info":"copy the following and paste into `index.html`\n\n```html\n<!doctype html><html lang=\"en\"><head>\n <meta charset=\"utf-8\">\n <meta http-equiv=\"X-UA-Compatible\" content=\"IE=edge\">\n <meta name=\"viewport\" content=\"width=device-width, minimum-scale=1, initial-scale=1, user-scalable=yes\">\n\n <title>Chartkick/VueJS Example - Node-RED UI Builder</title>\n <meta name=\"description\" content=\"Node-RED UI Builder - Chartkick/VueJS Example\">\n\n <link rel=\"icon\" href=\"./images/node-blue.ico\">\n\n <link type=\"text/css\" rel=\"stylesheet\" href=\"../uibuilder/vendor/bootstrap/dist/css/bootstrap.min.css\" />\n <link type=\"text/css\" rel=\"stylesheet\" href=\"../uibuilder/vendor/bootstrap-vue/dist/bootstrap-vue.css\" />\n\n <link rel=\"stylesheet\" href=\"./index.css\" media=\"all\">\n</head><body>\n <div id=\"app\">\n <b-container id=\"app_container\">\n\n <h1>\n Example of using <a href=\"https://chartkick.com/vue\" target=\"_blank\">Vue Chartkick</a>\n with uibuilder, VueJS and bootstrap-vue\n </h1>\n\n <b-row>\n <b-card cols=\"5\" class=\"mr-1\" header=\"Bar Chart\" border-variant=\"primary\" header-bg-variant=\"primary\" header-text-variant=\"white\" align=\"center\">\n <column-chart :data=\"[['Sun', 32], ['Mon', 46], ['Tue', 28]]\"></column-chart>\n </b-card>\n\n <b-card class=\"mr-1\" header=\"Line Chart\" border-variant=\"primary\" header-bg-variant=\"primary\" header-text-variant=\"white\" align=\"center\">\n <line-chart :data=\"lineChartData\"></line-chart>\n </b-card>\n\n <b-card class=\"mr-1\" header=\"Multi-Series Line Chart\" border-variant=\"primary\" header-bg-variant=\"primary\" header-text-variant=\"white\" align=\"center\">\n <line-chart :data=\"lineChartData2\"></line-chart>\n </b-card>\n\n <b-card class=\"w-100 mt-3 mb-3\" header=\"Area Chart\" border-variant=\"primary\" header-bg-variant=\"primary\" header-text-variant=\"white\" align=\"center\">\n <area-chart :data=\"areaChartData\"></area-chart>\n </b-card>\n\n <b-card class=\"mr-1\" header=\"Geo Chart (Google)\" border-variant=\"primary\" header-bg-variant=\"primary\" header-text-variant=\"white\" align=\"center\">\n <geo-chart width=\"800px\" :data=\"[['United States', 44], ['Germany', 23], ['Brazil', 22]]\"></geo-chart>\n </b-card>\n\n <b-card class=\"mr-1\" header=\"Timeline (Google)\" border-variant=\"primary\" header-bg-variant=\"primary\" header-text-variant=\"white\" align=\"center\">\n <timeline width=\"800px\" :data=\"[['Washington', '1789-04-29', '1797-03-03'], ['Adams', '1797-03-03', '1801-03-03']]\"></timeline>\n </b-card>\n\n </b-row>\n\n </b-container>\n </div>\n\n <script src=\"../uibuilder/vendor/socket.io/socket.io.js\"></script>\n <script src=\"../uibuilder/vendor/vue/dist/vue.min.js\"></script>\n <script src=\"../uibuilder/vendor/bootstrap-vue/dist/bootstrap-vue.js\"></script>\n\n <!-- Loading from CDN, use uibuilder to install packages and change to vendor links -->\n <script src=\"https://unpkg.com/[email protected]/dist/Chart.bundle.js\"></script> <!-- Chart.js -->\n <script src=\"https://www.gstatic.com/charts/loader.js\"></script> <!-- Google Charts -->\n <!-- <script src=\"https://code.highcharts.com/highcharts.js\"></script> HighCharts -->\n <script src=\"https://unpkg.com/[email protected]\"></script>\n\n <script src=\"./uibuilderfe.min.js\"></script> <!-- //prod version -->\n <script src=\"./index.js\"></script>\n\n</body></html>\n```","x":370,"y":40,"wires":[]},{"id":"7254bbb9.903ce4","type":"comment","z":"18cb249f.38bafb","name":"JavaScript","info":"Copy the following and paste into `index.js`\n\n```javascript\n/* jshint browser: true, esversion: 5 */\n/* globals document,Vue,window,uibuilder */\n// @ts-nocheck\n/*\n Copyright (c) 2019 Julian Knight (Totally Information)\n\n Licensed under the Apache License, Version 2.0 (the \"License\");\n you may not use this file except in compliance with the License.\n You may obtain a copy of the License at\n\n http://www.apache.org/licenses/LICENSE-2.0\n\n Unless required by applicable law or agreed to in writing, software\n distributed under the License is distributed on an \"AS IS\" BASIS,\n WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n See the License for the specific language governing permissions and\n limitations under the License.\n*/\n'use strict'\n\n/** @see https://github.com/TotallyInformation/node-red-contrib-uibuilder/wiki/Front-End-Library---available-properties-and-methods */\n\n// eslint-disable-next-line no-unused-vars\nvar app1 = new Vue({\n el: '#app',\n data: {\n // Single series line chart\n lineChartData: [\n ['Jan', 4], ['Feb', 2], ['Mar', 10], ['Apr', 5], ['May', 3],\n ],\n // Multi-series line chart\n lineChartData2: [\n {name: 'Workout', data: {'2017-01-01 00:00:00 -0800': 3, '2017-01-02 00:00:00 -0800': 4}},\n {name: 'Call parents', data: {'2017-01-01 00:00:00 -0800': 5, '2017-01-02 00:00:00 -0800': 3}},\n ],\n\n // Area chart\n areaChartData: [], //{\n //'2017-01-01 00:00:00 -0800': 2,\n //'2017-01-01 00:01:00 -0800': 5,\n //},\n\n }, // --- End of data --- //\n computed: {\n }, // --- End of computed --- //\n methods: {\n }, // --- End of methods --- //\n\n // Available hooks: init,mounted,updated,destroyed\n mounted: function(){\n /** **REQUIRED** Start uibuilder comms with Node-RED @since v2.0.0-dev3\n * Pass the namespace and ioPath variables if hosting page is not in the instance root folder\n * e.g. If you get continual `uibuilderfe:ioSetup: SOCKET CONNECT ERROR` error messages.\n * e.g. uibuilder.start('/nr/uib', '/nr/uibuilder/vendor/socket.io') // change to use your paths/names\n */\n uibuilder.start()\n\n var vueApp = this\n\n // Process new messages from Node-RED\n uibuilder.onChange('msg', function (newVal) {\n // We are assuming that msg.payload is an array like [datenum, value]\n\n // Add new element\n vueApp.areaChartData.push( new Array( (new Date(newVal.payload[0])), newVal.payload[1] ) )\n\n // If data array > 1000 points, keep it at that length by losing the first point\n if ( vueApp.areaChartData.length > 1000 ) vueApp.areaChartData.shift()\n\n //console.log(vueApp.areaChartData)\n })\n\n } // --- End of mounted hook --- //\n\n}) // --- End of app1 --- //\n\n// EOF\n```\n","x":480,"y":40,"wires":[]}]
<!doctype html><html lang="en"><head>
<meta charset="utf-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, minimum-scale=1, initial-scale=1, user-scalable=yes">
<title>Chartkick/VueJS Example - Node-RED UI Builder</title>
<meta name="description" content="Node-RED UI Builder - Chartkick/VueJS Example">
<link rel="icon" href="./images/node-blue.ico">
<link type="text/css" rel="stylesheet" href="../uibuilder/vendor/bootstrap/dist/css/bootstrap.min.css" />
<link type="text/css" rel="stylesheet" href="../uibuilder/vendor/bootstrap-vue/dist/bootstrap-vue.css" />
<link rel="stylesheet" href="./index.css" media="all">
</head><body>
<div id="app">
<b-container id="app_container">
<h1>
Example of using <a href="https://chartkick.com/vue" target="_blank">Vue Chartkick</a>
with uibuilder, VueJS and bootstrap-vue
</h1>
<b-row>
<b-card cols="5" class="mr-1" header="Bar Chart" border-variant="primary" header-bg-variant="primary" header-text-variant="white" align="center">
<column-chart :data="[['Sun', 32], ['Mon', 46], ['Tue', 28]]"></column-chart>
</b-card>
<b-card class="mr-1" header="Line Chart" border-variant="primary" header-bg-variant="primary" header-text-variant="white" align="center">
<line-chart :data="lineChartData"></line-chart>
</b-card>
<b-card class="mr-1" header="Multi-Series Line Chart" border-variant="primary" header-bg-variant="primary" header-text-variant="white" align="center">
<line-chart :data="lineChartData2"></line-chart>
</b-card>
<b-card class="w-100 mt-3 mb-3" header="Area Chart" border-variant="primary" header-bg-variant="primary" header-text-variant="white" align="center">
<area-chart :data="areaChartData"></area-chart>
</b-card>
<b-card class="mr-1" header="Geo Chart (Google)" border-variant="primary" header-bg-variant="primary" header-text-variant="white" align="center">
<geo-chart width="800px" :data="[['United States', 44], ['Germany', 23], ['Brazil', 22]]"></geo-chart>
</b-card>
<b-card class="mr-1" header="Timeline (Google)" border-variant="primary" header-bg-variant="primary" header-text-variant="white" align="center">
<timeline width="800px" :data="[['Washington', '1789-04-29', '1797-03-03'], ['Adams', '1797-03-03', '1801-03-03']]"></timeline>
</b-card>
</b-row>
</b-container>
</div>
<script src="../uibuilder/vendor/socket.io/socket.io.js"></script>
<script src="../uibuilder/vendor/vue/dist/vue.min.js"></script>
<script src="../uibuilder/vendor/bootstrap-vue/dist/bootstrap-vue.js"></script>
<!-- Loading from CDN, use uibuilder to install packages and change to vendor links -->
<script src="https://unpkg.com/[email protected]/dist/Chart.bundle.js"></script> <!-- Chart.js -->
<script src="https://www.gstatic.com/charts/loader.js"></script> <!-- Google Charts -->
<!-- <script src="https://code.highcharts.com/highcharts.js"></script> HighCharts -->
<script src="https://unpkg.com/[email protected]"></script>
<script src="./uibuilderfe.min.js"></script> <!-- //prod version -->
<script src="./index.js"></script>
</body></html>
/* jshint browser: true, esversion: 5 */
/* globals document,Vue,window,uibuilder */
// @ts-nocheck
/*
Copyright (c) 2019 Julian Knight (Totally Information)
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/
'use strict'
/** @see https://github.com/TotallyInformation/node-red-contrib-uibuilder/wiki/Front-End-Library---available-properties-and-methods */
// eslint-disable-next-line no-unused-vars
var app1 = new Vue({
el: '#app',
data: {
// Single series line chart
lineChartData: [
['Jan', 4], ['Feb', 2], ['Mar', 10], ['Apr', 5], ['May', 3],
],
// Multi-series line chart
lineChartData2: [
{name: 'Workout', data: {'2017-01-01 00:00:00 -0800': 3, '2017-01-02 00:00:00 -0800': 4}},
{name: 'Call parents', data: {'2017-01-01 00:00:00 -0800': 5, '2017-01-02 00:00:00 -0800': 3}},
],
// Area chart
areaChartData: [], //{
//'2017-01-01 00:00:00 -0800': 2,
//'2017-01-01 00:01:00 -0800': 5,
//},
}, // --- End of data --- //
computed: {
}, // --- End of computed --- //
methods: {
}, // --- End of methods --- //
// Available hooks: init,mounted,updated,destroyed
mounted: function(){
/** **REQUIRED** Start uibuilder comms with Node-RED @since v2.0.0-dev3
* Pass the namespace and ioPath variables if hosting page is not in the instance root folder
* e.g. If you get continual `uibuilderfe:ioSetup: SOCKET CONNECT ERROR` error messages.
* e.g. uibuilder.start('/nr/uib', '/nr/uibuilder/vendor/socket.io') // change to use your paths/names
*/
uibuilder.start()
var vueApp = this
// Process new messages from Node-RED
uibuilder.onChange('msg', function (newVal) {
// We are assuming that msg.payload is an array like [datenum, value]
// Add new element
vueApp.areaChartData.push( new Array( (new Date(newVal.payload[0])), newVal.payload[1] ) )
// If data array > 1000 points, keep it at that length by losing the first point
if ( vueApp.areaChartData.length > 1000 ) vueApp.areaChartData.shift()
//console.log(vueApp.areaChartData)
})
} // --- End of mounted hook --- //
}) // --- End of app1 --- //
// EOF
Please feel free to add comments to the page (clearly mark with your initials & please add a commit msg so we know what has changed). You can contact me in the Discourse forum, or raise an issue here in GitHub! I will make sure all comments & suggestions are represented here.
-
Walkthrough 🔗 Getting started
-
In Progress and To Do 🔗 What's coming up for uibuilder?
-
Awesome uibuilder Examples, tutorials, templates and references.
-
How To
- How to send data when a client connects or reloads the page
- Send messages to a specific client
- Cache & Replay Messages
- Cache without a helper node
- Use webpack to optimise front-end libraries and code
- How to contribute & coding standards
- How to use NGINX as a proxy for Node-RED
- How to manage packages manually
- How to upload a file from the browser to Node-RED
-
Vanilla HTML/JavaScript examples
-
VueJS general hints, tips and examples
- Load Vue (v2 or v3) components without a build step (modern browsers only)
- How to use webpack with VueJS (or other frameworks)
- Awesome VueJS - Tips, info & libraries for working with Vue
- Components that work
-
VueJS v3 hints, tips and examples
-
VueJS v2 hints, tips and examples
- Dynamically load .vue files without a build step (Vue v2)
- Really Simple Example (Quote of the Day)
- Example charts using Chartkick, Chart.js, Google
- Example Gauge using vue-svg-gauge
- Example charts using ApexCharts
- Example chart using Vue-ECharts
- Example: debug messages using uibuilder & Vue
- Example: knob/gauge widget for uibuilder & Vue
- Example: Embedded video player using VideoJS
- Simple Button Acknowledgement Example Thanks to ringmybell
- Using Vue-Router without a build step Thanks to AFelix
- Vue Canvas Knob Component Thanks to Klaus Zerbe
-
Examples for other frameworks (check version before trying)
- Basic jQuery example - Updated for uibuilder v6.1
- ReactJS with no build - updated for uibuilder v5/6
-
Examples for other frameworks (may not work, out-of-date)
-
Outdated Pages (Historic only)
- v1 Examples (these need updating to uibuilder v2/v3/v4/v5)