My goal was to be able to add/remove ui elements during flow execution (an example I don't know how many IoT devices will connect so I need to add them to UI on the fly).
It's quite simple to generate UI elements using Angular directives and dashboard template but the main problem is how to correctly resize UI. Below example gives you ability to add and remove UI buttons, after pressing dynamic button you will get notification with button number. Ther is still problem with correctly resizing group node. I've tried to remove "md-card" directives from the below code but after that dashbord resize correctly (!) only if you refresh the web page (is there any method to inform UI that page need refresh?). Also during adding/removing dynamic elements group node sometimes moving slightly lef or right.
[{"id":"eeb6447e.7c4358","type":"ui_button","z":"785527b6.ef937","name":"","group":"b91e0515.48b06","order":0,"width":0,"height":0,"label":"Add","color":"","icon":"","payload":"inc","payloadType":"str","topic":"","x":110,"y":120,"wires":[["8c30d944.b0ce"]]},{"id":"5155a9b0.a4541","type":"ui_button","z":"785527b6.ef937","name":"","group":"b91e0515.48b06","order":0,"width":0,"height":0,"label":"Remove","color":"","icon":"","payload":"dec","payloadType":"str","topic":"","x":100,"y":160,"wires":[["8c30d944.b0ce"]]},{"id":"a75ac227.6e9698","type":"ui_text","z":"785527b6.ef937","group":"b91e0515.48b06","order":0,"width":0,"height":0,"name":"","label":"Item count","format":"{{msg.payload}}","layout":"row-spread","x":470,"y":100,"wires":[]},{"id":"8c30d944.b0ce","type":"function","z":"785527b6.ef937","name":"inc/dec","func":"var count = flow.get('nodeCount') || 0;\n\nif (msg.payload==\"inc\")\n{\n count++;\n} else if (msg.payload==\"dec\")\n{\n if (count>0) count--;\n}\n\nflow.set('nodeCount',count);\n\nmsg.payload=count;\n\nreturn msg;","outputs":1,"noerr":0,"x":280,"y":120,"wires":[["a75ac227.6e9698","750db4cc.d7ee7c"]]},{"id":"750db4cc.d7ee7c","type":"function","z":"785527b6.ef937","name":"list gen","func":"var count = msg.payload;\nvar xxx=[];\nfor(i=0; i<count; i++)\n{\n xxx.push({\n text: \"Item \"+(i+1),\n payload: (i+1)\n });\n}\nmsg.payload=xxx;\nmsg.w=6;\nmsg.h=count;\nreturn msg;","outputs":1,"noerr":0,"x":460,"y":140,"wires":[["587e19a4.f76d7"]]},{"id":"50c88552.39157c","type":"inject","z":"785527b6.ef937","name":"","topic":"","payload":"1st run","payloadType":"str","repeat":"","crontab":"","once":true,"x":110,"y":80,"wires":[["8c30d944.b0ce"]]},{"id":"587e19a4.f76d7","type":"ui_template","z":"785527b6.ef937","group":"b91e0515.48b06","name":"","order":0,"width":"0","height":"0","format":"<md-card ui-card-size=\"{{msg.w}}x{{msg.h}}\">\n\n<div ng-repeat=\"xxx in msg.payload\">\n<md-card ui-card-size=\"{{msg.w}}x1\">\n<md-button ng-click=\"send({payload: xxx.payload})\">\n {{xxx.text}}\n</md-button>\n</md-card>\n</div>\n\n</md-card>\n","storeOutMessages":false,"fwdInMessages":false,"x":620,"y":140,"wires":[["c5fdd0f1.39449"]]},{"id":"80161f5.34e53e","type":"ui_button","z":"785527b6.ef937","name":"","group":"b91e0515.48b06","order":0,"width":0,"height":0,"label":"do nothing","color":"","icon":"","payload":"","payloadType":"str","topic":"","x":110,"y":200,"wires":[[]]},{"id":"c5fdd0f1.39449","type":"ui_toast","z":"785527b6.ef937","position":"top right","displayTime":"3","name":"","x":810,"y":140,"wires":[]},{"id":"4cd46b05.e3417c","type":"comment","z":"785527b6.ef937","name":"dynamic dashboard button list","info":"","x":160,"y":40,"wires":[]},{"id":"b91e0515.48b06","type":"ui_group","z":"","name":"Dynamic group","tab":"42cdc43c.39e664","order":1,"disp":true,"width":"6"},{"id":"42cdc43c.39e664","type":"ui_tab","z":"","name":"Dynamic test","icon":"dashboard","order":3}]