Hi everyone,
Have been exploring the ui_template dashboard widget and find it very powerful. I can create basically a single page app with d3 charts and custom gauges etc, all in the one template. Saves having to organise everything using Node-reds colums format.
I am running into a recurring issue in that elements that are sized inside of a container div at 100% the ui_template widget size size, and their 100% sized children seem to be sized before the node is fully rendered and end up small. Example here (outlind of container div shown as border):
Once the second message comes through, all renders fine, the zoom sliders work, etc. like below:
So the container div sizes fine, but the children charts and gauges at 100% are inconsistent. In this case the child SVG is sized to 100% using css but this issue is consistent accross D3 charts, canvas charts, and canvas gauges, but the parent container div is fine. Baffling.
This has been eating at me for some time, and I just can't seem to beat it. I think it may be angular related and it appears to be a problem in the wider community, I just couldn't figure out how to solve for the AngularJS version that Node Red uses.
Does any one have a clue to address this sizing on load issue? If i put the sizing in the update portion of the scope watches, it size properly on the second message, but i don't want to wait for second message, nor do I want to do resize logic on every message either.
Code below:
[{"id":"c8dc9b49.abc738","type":"template","z":"2c6e5ff2.bbfe3","name":"NVD3 Template","field":"template","fieldType":"msg","format":"html","syntax":"mustache","template":"<script src=\"../d3/d3.min.js\"></script>\n<script src=\"../nvd3/nv.d3.min.js\"></script>\n<link rel=\"stylesheet\" href=\"../nvd3/nv.d3.min.css\">\n\n<style>\n #chartTest, svg {\n margin: 0px;\n padding: 0px;\n height: 100%;\n width: 100%;\n border: solid 1px;\n box-sizing: border-box;\n }\n</style>\n\n<div id=\"chartTest\" class='with-3d-shadow with-transitions'>\n <svg> </svg>\n</div>\n\n\n\n\n\n\n\n<script>\n\n\n//-- This is the angular message handler function used to receive messages -----\n//------------------------------------------------------------------------------\n(function(scope) { \n // This portion of the function fires only once on first message received and is the local 'global' scope\n \n var chart = nv.models.linePlusBarChart()\n .margin({top: 50, right: 60, bottom: 30, left: 60})\n .legendRightAxisHint(' [Using Right Axis]')\n .color(d3.scale.category10().range());\n \n chart.xAxis.tickFormat(function(d) { \n return d3.time.format('%x')(new Date(d));\n }).showMaxMin(false);\n\n chart.x2Axis.tickFormat(function(d) {\n return d3.time.format('%x')(new Date(d))\n }).showMaxMin(false);\n\n chart.y1Axis.tickFormat(function(d) {\n return d3.format('0.1f')(d) + ' mm ';\n });\n chart.bars.forceY([0]).padData(false);\n\n chart.y2Axis.tickFormat(function(d) {\n return ' ' + d3.format('0f')(d)+ ' mm';\n });\n chart.bars.forceY([0]).padData(false);\n\n\n // This function fires everytime a msg.payload is received\n scope.$watch('msg.payload', function(data) { \n\n\n chart.bars.forceY([0]);\n\n d3.select('#chartTest svg')\n .datum(formatData(data))\n .transition().duration(500)\n .call(chart);\n \n nv.utils.windowResize(chart.update);\n \n return chart;\n\n });\n \n \n function formatData(data){\n var formattedData = [{\n key: data[0].series[0],\n values: data[0].data[0],\n bar: true\n },{\n key: data[0].series[1],\n values: data[0].data[1]\n }];\n return formattedData;\n }\n})(scope);\n\n\n\n\n\n/*\nnv.addGraph(function() {\n var chart = nv.models.linePlusBarChart()\n .margin({top: 30, right: 60, bottom: 50, left: 70})\n .x(function(d,i) { return i })\n .y(function(d) { return d[1] })\n .color(d3.scale.category10().range())\n ;\n\n chart.xAxis\n .showMaxMin(false)\n .tickFormat(function(d) {\n var dx = data[0].values[d] && data[0].values[d][0] || 0;\n return d3.time.format('%x')(new Date(dx))\n });\n\n chart.y1Axis\n .tickFormat(d3.format(',f'));\n\n chart.y2Axis\n .tickFormat(function(d) { return '$' + d3.format(',f')(d) });\n\n chart.bars.forceY([0]);\n\n d3.select('#chart svg')\n .datum(data)\n .transition().duration(500)\n .call(chart)\n ;\n\n nv.utils.windowResize(chart.update);\n\n return chart;\n});\n*/\n\n\n\n/*\n nv.addGraph(function() {\n chart = nv.models.linePlusBarChart()\n .margin({top: 50, right: 60, bottom: 30, left: 60})\n .legendRightAxisHint(' [Using Right Axis]')\n .color(d3.scale.category10().range());\n\n chart.xAxis.tickFormat(function(d) {\n return d3.time.format('%x')(new Date(d))\n }).showMaxMin(false);\n\n chart.y1Axis.tickFormat(function(d) { return d3.format('0.1f')(d) + ' mm ' });\n chart.bars.forceY([0]).padData(false);\n\n chart.y2Axis.tickFormat(function(d) { return ' ' + d3.format('0f')(d)+ ' mm' });\n chart.bars.forceY([0]).padData(false);\n\n //chart.x2Axis.tickFormat(function(d) {\n // return d3.time.format('%x')(new Date(d))\n //}).showMaxMin(false);\n\n chart.dispatch.on('stateChange', function(e) { nv.log('New State:', JSON.stringify(e)); });\n nv.utils.windowResize(chart.update);\n return chart; \n });\n\n // This function fires everytime a msg.payload is received\n scope.$watch('msg.payload', function(data) { \n d3.select('#chartTest svg')\n .datum(formatData(data))\n .transition().duration(500).call(chart);\n\n });\n*/\n\n\n</script>\n\n\n\n\n\n\n\n","output":"str","x":780,"y":340,"wires":[["22237b3e.6e93a4"]]}]
Thanks in advance!
Rob