# UI Template Edit msg.payload then Output

**URL:** <https://discourse.nodered.org/t/ui-template-edit-msg-payload-then-output/85694>\
**Category:** Dashboard\
**Tags:** node-red-dashboard, ui-template\
**Created:** [20 February 2024 10:25 UTC](https://discourse.nodered.org/t/ui-template-edit-msg-payload-then-output/85694 "2024-02-20T10:25:44Z")\
**Posts on this page:** 10\
**Page:** 1

<div class="post-metadata">

**Author:** ![Ideasbuilders](https://avatars.discourse-cdn.com/v4/letter/i/5f8ce5/32.png) [@Ideasbuilders](https://discourse.nodered.org/u/Ideasbuilders)\
**Post date:** [20 February 2024 10:25 UTC](https://discourse.nodered.org/t/ui-template-edit-msg-payload-then-output/85694/1 "2024-02-20T10:25:44Z")

</div>

I'm making a dashboard UI table.

I wanted to achieve the msg.payload can be updated from the ui-template then output to other nodes.

Is there any thing I could add to make this happen?

```auto
 <body>
 <table>
     <tr>
       <th>Machine</th>
       <th>Target Time</th>
       <th>Quantity</th>
       <th>
         <input type="checkbox" ng-model="all">
         Reset
       </th>
     </tr>
     <tr ng-repeat="machine in msg.payload.factory">
       <td>{{machine.name}}</td>
       <td contenteditable>{{machine.min}}</td>
       <td contenteditable>{{machine.max}}</td>
       <td>
         <input type="checkbox" ng-checked="all">
       </td>
     </tr>
   </table>
   <md-button ng-model="msg.payload" ng-click="send(msg)">
     Submit
   </md-button>
   <p>{{msg.payload}}</p>
   </div>
 </body>

```

This are the data that passed to the template

```auto
 msg.payload = {
   factory: {
     machine00: {
       min: 1,
       max: 1,
       reset: false,
       name: "MC-TM-01"
     },
     machine01: {
       min: 1,
       max: 1,
       reset: false,
       name: "MC-TM-02"
     }
   }
 }

```

---

<div class="post-metadata">

**Author:** ![E1cid](https://sea2.discourse-cdn.com/flex026/user_avatar/discourse.nodered.org/e1cid/32/77971_2.png) [@E1cid](https://discourse.nodered.org/u/E1cid)\
**Post date:** [20 February 2024 13:18 UTC](https://discourse.nodered.org/t/ui-template-edit-msg-payload-then-output/85694/2 "2024-02-20T13:18:15Z")

</div>

Not really enough info to make any full suggestions, I.e all payload or a row or a cell.

You may want to look at ui-table (Based on tabulator 4.7), or even tabulator library [Documentation | Tabulator](https://www.tabulator.info/docs/5.6).

---

<div class="post-metadata">

**Author:** ![Ideasbuilders](https://avatars.discourse-cdn.com/v4/letter/i/5f8ce5/32.png) [@Ideasbuilders](https://discourse.nodered.org/u/Ideasbuilders)\
**Post date:** [22 February 2024 06:32 UTC](https://discourse.nodered.org/t/ui-template-edit-msg-payload-then-output/85694/3 "2024-02-22T06:32:53Z")

</div>

I've done the table part already,

 ![image](https://us1.discourse-cdn.com/flex026/uploads/nodered/original/3X/0/1/01558eec1c9daa6520cea9d6618ef732459e6f80.png)

What I needed is after the original payload is passed to the table,  
It could be edited from the table and output the whole edited payload by pressing the submit button

Used the etable before, but the tick box requires 2 clicks to change it thus I tried to make the custom table

---

<div class="post-metadata">

**Author:** ![E1cid](https://sea2.discourse-cdn.com/flex026/user_avatar/discourse.nodered.org/e1cid/32/77971_2.png) [@E1cid](https://discourse.nodered.org/u/E1cid)\
**Post date:** [22 February 2024 11:07 UTC](https://discourse.nodered.org/t/ui-template-edit-msg-payload-then-output/85694/4 "2024-02-22T11:07:12Z")

</div>

You are reinventing the wheel.

Ui-table will allow you to edit the cells of the table , once edited click row to send update  
here is an example

```auto
[{"id":"54197d9fec778b15","type":"inject","z":"36348c32365b6b66","name":"","props":[{"p":"payload"},{"p":"topic","vt":"str"}],"repeat":"","crontab":"","once":false,"onceDelay":0.1,"topic":"","payload":"[{\"id\":0,\"machine\":\"aa-bb-11\",\"targetTime\":12,\"quantity\":3,\"reset\":false},{\"id\":1,\"machine\":\"aa-bb-12\",\"targetTime\":12,\"quantity\":3,\"reset\":false}]","payloadType":"json","x":970,"y":240,"wires":[["e60166842e8e4533"]]},{"id":"e60166842e8e4533","type":"function","z":"36348c32365b6b66","name":"Format for Table","func":"let table = flow.get(\"table\") || [];\nif(table.length < 1){\n let ui_control = {\n \"tabulator\": {\n pagination:\"local\",\n paginationSize:8,\n paginationButtonCount:5,\n selectable:1,\n locale:true,\n layout:\"fitColumns\",\n columns:[\n {\n title:\"Machine\", \n field:\"machine\",\n formatter: \"plaintext\", \n editor:\"input\",\n mask:\"AA-AA-99\",\n maskAutoFill:true, \n editorParams:{\n elementAttributes:{\n maxlength:\"8\", //set the maximum character length of the textarea element to 10 characters\n }\n }\n },\n {\n title:\"Target Time\", \n field:\"targetTime\",\n formatter: \"plaintext\", \n editor:\"input\", \n editorParams:{\n elementAttributes:{\n maxlength:\"10\", //set the maximum character length of the textarea element to 10 characters\n },\n mask:\"9999999999\"\n }\n },\n {\n title:\"Qyantity\", \n field:\"quantity\",\n formatter: \"plaintext\",\n editor:\"input\", \n editorParams:{\n elementAttributes:{\n maxlength:\"4\", //set the maximum character length of the textarea element to 10 characters\n },\n mask:\"9999\"\n }\n },\n {\n title:\"reset\", \n field:\"reset\", \n formatter:\"tickCross\",\n editor:\"tickCross\"\n }\n] \n }\n }\nnode.send({ui_control}) \n}\nflow.set(\"table\",msg.payload)\nmsg.payload = {\n command:\"replaceData\",\n arguments:[msg.payload]\n}\nreturn msg;","outputs":1,"timeout":"","noerr":0,"initialize":"","finalize":"","libs":[],"x":1180,"y":240,"wires":[["828a8f6f187a9559"]]},{"id":"828a8f6f187a9559","type":"ui_table","z":"36348c32365b6b66","group":"6305d8128da6cbab","name":"","order":1,"width":"17","height":"6","columns":[],"outputs":1,"cts":true,"x":1350,"y":240,"wires":[["461a02ef6c2ad5de"]]},{"id":"461a02ef6c2ad5de","type":"change","z":"36348c32365b6b66","name":"","rules":[{"t":"set","p":"table[msg.row]","pt":"flow","to":"payload","tot":"msg"}],"action":"","property":"","from":"","to":"","reg":false,"x":1550,"y":240,"wires":[[]]},{"id":"fbaf2bcb6253dc30","type":"ui_button","z":"36348c32365b6b66","name":"","group":"6305d8128da6cbab","order":2,"width":0,"height":0,"passthru":false,"label":"gettable data","tooltip":"","color":"","bgcolor":"","className":"","icon":"","payload":"","payloadType":"str","topic":"getdata","topicType":"str","x":990,"y":300,"wires":[["b94e9f024fe1b1b2"]]},{"id":"b94e9f024fe1b1b2","type":"change","z":"36348c32365b6b66","name":"","rules":[{"t":"set","p":"payload","pt":"msg","to":"table","tot":"flow"}],"action":"","property":"","from":"","to":"","reg":false,"x":1180,"y":300,"wires":[["402f38eb0fa3350b"]]},{"id":"402f38eb0fa3350b","type":"debug","z":"36348c32365b6b66","name":"debug 2475","active":true,"tosidebar":true,"console":false,"tostatus":false,"complete":"true","targetType":"full","statusVal":"","statusType":"auto","x":1370,"y":300,"wires":[]},{"id":"6305d8128da6cbab","type":"ui_group","name":"Group 1","tab":"b927390ff1bafb51","order":1,"disp":true,"width":17},{"id":"b927390ff1bafb51","type":"ui_tab","name":"bridge","icon":"dashboard","order":20,"disabled":false,"hidden":false}]

```

[Base on Tabulator 4.7](https://www.tabulator.info/docs/4.7/edit), but you could get more functionality by using tabulate 5+ direct in the template Or try dashboard 2 tables.

Oh two clicks, that must be a deal breaker, Have you tried adding a html check box.

To do it in ui-template node you would have to add text inputs to each td, then use ng-model, ng-blur and ng-value to send the row and property and changed data, and update the stored data.  
e.g.

```auto
[{"id":"17f84e1550b7a06c","type":"ui_button","z":"36348c32365b6b66","name":"","group":"6305d8128da6cbab","order":2,"width":0,"height":0,"passthru":false,"label":"set data","tooltip":"","color":"","bgcolor":"","className":"","icon":"","payload":"","payloadType":"str","topic":"topic","topicType":"msg","x":1180,"y":180,"wires":[["5c135f0b481561db"]]},{"id":"fbaf2bcb6253dc30","type":"ui_button","z":"36348c32365b6b66","name":"","group":"6305d8128da6cbab","order":2,"width":0,"height":0,"passthru":false,"label":"gettable data","tooltip":"","color":"","bgcolor":"","className":"","icon":"","payload":"","payloadType":"str","topic":"getdata","topicType":"str","x":990,"y":300,"wires":[["b94e9f024fe1b1b2"]]},{"id":"b94e9f024fe1b1b2","type":"change","z":"36348c32365b6b66","name":"","rules":[{"t":"set","p":"payload","pt":"msg","to":"table","tot":"flow"}],"action":"","property":"","from":"","to":"","reg":false,"x":1340,"y":300,"wires":[["402f38eb0fa3350b","797f37eb7bafc6f0"]]},{"id":"402f38eb0fa3350b","type":"debug","z":"36348c32365b6b66","name":"debug 2475","active":true,"tosidebar":true,"console":false,"tostatus":false,"complete":"true","targetType":"full","statusVal":"","statusType":"auto","x":1670,"y":300,"wires":[]},{"id":"797f37eb7bafc6f0","type":"json","z":"36348c32365b6b66","name":"","property":"payload","action":"","pretty":true,"x":1330,"y":360,"wires":[["cd459f1561f51e88"]]},{"id":"cd459f1561f51e88","type":"ui_text","z":"36348c32365b6b66","group":"6305d8128da6cbab","order":3,"width":"17","height":"4","name":"","label":"","format":"<pre>{{msg.payload}}</pre>","layout":"row-spread","className":"","style":false,"font":"","fontSize":16,"color":"#000000","x":1470,"y":360,"wires":[]},{"id":"461a02ef6c2ad5de","type":"change","z":"36348c32365b6b66","name":"","rules":[{"t":"set","p":"table[msg.id][msg.prop]","pt":"flow","to":"payload","tot":"msg"}],"action":"","property":"","from":"","to":"","reg":false,"x":1730,"y":240,"wires":[[]]},{"id":"bb259756667c55d0","type":"ui_template","z":"36348c32365b6b66","group":"6305d8128da6cbab","name":"","order":2,"width":0,"height":0,"format":"<table>\n <tr ng-repeat=\"row in msg.payload\">\n <td><input \n ng-model=\"machineRow\"\n ng-value=\"row.machine\"\n ng-blur=\"send({payload:(machineRow||row.machine),id:row.id,prop:'machine'})\" \n type=\"text\" \n required minlength=\"8\" \n maxlength=\"8\" \n size=\"10\"\n /></td>\n </tr>\n</table>","storeOutMessages":false,"fwdInMessages":false,"resendOnRefresh":true,"templateScope":"local","className":"","x":1460,"y":240,"wires":[["461a02ef6c2ad5de"]]},{"id":"5c135f0b481561db","type":"change","z":"36348c32365b6b66","name":"","rules":[{"t":"set","p":"payload","pt":"msg","to":"[{\"id\":0,\"machine\":\"aa-bb-11\",\"targetTime\":12,\"quantity\":3,\"reset\":false},{\"id\":1,\"machine\":\"aa-bb-12\",\"targetTime\":12,\"quantity\":3,\"reset\":false}]","tot":"json"},{"t":"set","p":"table","pt":"flow","to":"payload","tot":"msg"}],"action":"","property":"","from":"","to":"","reg":false,"x":1280,"y":240,"wires":[["bb259756667c55d0"]]},{"id":"6305d8128da6cbab","type":"ui_group","name":"Group 1","tab":"b927390ff1bafb51","order":1,"disp":true,"width":17},{"id":"b927390ff1bafb51","type":"ui_tab","name":"bridge","icon":"dashboard","order":20,"disabled":false,"hidden":false}]

```

---

<div class="post-metadata">

**Author:** ![shrickus](https://sea2.discourse-cdn.com/flex026/user_avatar/discourse.nodered.org/shrickus/32/517_2.png) [@shrickus](https://discourse.nodered.org/u/shrickus)\
**Post date:** [22 February 2024 17:23 UTC](https://discourse.nodered.org/t/ui-template-edit-msg-payload-then-output/85694/5 "2024-02-22T17:23:08Z")

</div>

> [@E1cid](#):
>
> To do it in ui-template node you would have to add text inputs to each td, then use ng-model, ng-blur and ng-value to send the row and property and changed data, and update the stored data.

Another fine solution from @E1cid -- above and beyond the initial request... thanks for all of your well-thought out answers!

Are all of these flows captured somewhere that the rest of this community can search later, when we run into similar questions? I dare say that I'll probably never be able to find this one-line flow if/when I need it -- there is just too much conversation text to read through to be "searchable", at least for me.

So is there a gist somewhere, or an entry in the flows library, where I can find the same sample flow? Thanks again.  
\_\_  
Steve

---

<div class="post-metadata">

**Author:** ![Steve-Mcl](https://sea2.discourse-cdn.com/flex026/user_avatar/discourse.nodered.org/steve-mcl/32/4826_2.png) [@Steve-Mcl](https://discourse.nodered.org/u/Steve-Mcl)\
**Post date:** [22 February 2024 17:26 UTC](https://discourse.nodered.org/t/ui-template-edit-msg-payload-then-output/85694/6 "2024-02-22T17:26:42Z")

</div>

You can bookmark posts

![image](https://us1.discourse-cdn.com/flex026/uploads/nodered/original/3X/6/2/62041101222e23ce4a692afc46d2e34c0b685e05.png)

You can also add entries to the flows lib yourself. I have done this and know where to find all my entries really easily (I click my avatar after logging into the flows lib)

I realise thats sounds a little like a RTM response but it is actually better for your own organisation than having to search everyone's flows on the flows lib.

---

<div class="post-metadata">

**Author:** ![E1cid](https://sea2.discourse-cdn.com/flex026/user_avatar/discourse.nodered.org/e1cid/32/77971_2.png) [@E1cid](https://discourse.nodered.org/u/E1cid)\
**Post date:** [22 February 2024 17:46 UTC](https://discourse.nodered.org/t/ui-template-edit-msg-payload-then-output/85694/7 "2024-02-22T17:46:59Z")

</div>

> [@shrickus](#):
>
> Another fine solution from @E1cid -- above and beyond the initial request... thanks for all of your well-thought out answers!
> 
> Are all of these flows captured somewhere that the rest of this community can search later,

Thank you for you kind words.

I do tend to keep copies of them locally. Maybe I should add then to my git, I am pretty bad at doing that. Or may be give the examples a good title in the post, so easier to search

Just for info here is another example

Edit ui-template table and store data locally using localStorage, with command to get updated table

```auto
[{"id":"17f84e1550b7a06c","type":"ui_button","z":"36348c32365b6b66","name":"","group":"6305d8128da6cbab","order":2,"width":0,"height":0,"passthru":false,"label":"set data","tooltip":"","color":"","bgcolor":"","className":"","icon":"","payload":"[]","payloadType":"json","topic":"topic","topicType":"msg","x":1180,"y":180,"wires":[["5c135f0b481561db"]]},{"id":"5c135f0b481561db","type":"change","z":"36348c32365b6b66","name":"","rules":[{"t":"set","p":"payload","pt":"msg","to":"[{\"id\":0,\"machine\":\"aa-bb-11\",\"targetTime\":12,\"quantity\":3,\"reset\":false},{\"id\":1,\"machine\":\"aa-bb-12\",\"targetTime\":12,\"quantity\":3,\"reset\":false}]","tot":"json"}],"action":"","property":"","from":"","to":"","reg":false,"x":1280,"y":240,"wires":[["bb259756667c55d0"]]},{"id":"bb259756667c55d0","type":"ui_template","z":"36348c32365b6b66","group":"6305d8128da6cbab","name":"","order":2,"width":0,"height":0,"format":"<table>\n <tr ng-repeat=\"row in msg.payload\">\n <td><input \n ng-model=\"machine\"\n ng-value=\"row.machine\"\n ng-blur=\"send_row_data($index,'machine',(machine||row.machine))\" \n type=\"text\" \n required minlength=\"8\" \n maxlength=\"8\" \n size=\"10\"\n /></td>\n </tr>\n</table>\n<script>\n(function(scope) {\n scope.send_row_data = function (id, prop, payload) { \n let stored = localStorage.getItem(\"table\");\n let obj_stored = JSON.parse(stored);\n if(obj_stored[id][prop]){\n obj_stored[id][prop] = payload;\n localStorage.setItem(\"table\", JSON.stringify(obj_stored));\n }\n //scope.send({payload,id,prop}); \n }\n scope.$watch('msg', function(msg) {\n if ( msg.payload && Array.isArray(msg.payload) && msg.payload.length > 0 ) {\n //alert(\"set\");\n localStorage.setItem(\"table\", JSON.stringify(msg.payload));\n //alert(localStorage.getItem(\"table\"))\n }else if(msg.payload && msg.payload === \"output\"){\n //alert(\"get\")\n let output = localStorage.getItem(\"table\");\n scope.send({payload:JSON.parse(output)});\n }\n })\n})(scope);\n</script>","storeOutMessages":false,"fwdInMessages":false,"resendOnRefresh":false,"templateScope":"local","className":"","x":1460,"y":240,"wires":[["402f38eb0fa3350b","797f37eb7bafc6f0"]]},{"id":"fbaf2bcb6253dc30","type":"ui_button","z":"36348c32365b6b66","name":"","group":"6305d8128da6cbab","order":2,"width":0,"height":0,"passthru":false,"label":"gettable data","tooltip":"","color":"","bgcolor":"","className":"","icon":"","payload":"output","payloadType":"str","topic":"getdata","topicType":"str","x":1110,"y":300,"wires":[["bb259756667c55d0"]]},{"id":"402f38eb0fa3350b","type":"debug","z":"36348c32365b6b66","name":"debug 2475","active":true,"tosidebar":true,"console":false,"tostatus":false,"complete":"true","targetType":"full","statusVal":"","statusType":"auto","x":1650,"y":240,"wires":[]},{"id":"797f37eb7bafc6f0","type":"json","z":"36348c32365b6b66","name":"","property":"payload","action":"","pretty":true,"x":1330,"y":360,"wires":[["cd459f1561f51e88"]]},{"id":"cd459f1561f51e88","type":"ui_text","z":"36348c32365b6b66","group":"6305d8128da6cbab","order":3,"width":"17","height":"4","name":"","label":"","format":"<pre>{{msg.payload}}</pre>","layout":"row-spread","className":"","style":false,"font":"","fontSize":16,"color":"#000000","x":1470,"y":360,"wires":[]},{"id":"6305d8128da6cbab","type":"ui_group","name":"Group 1","tab":"b927390ff1bafb51","order":1,"disp":true,"width":17},{"id":"b927390ff1bafb51","type":"ui_tab","name":"bridge","icon":"dashboard","order":20,"disabled":false,"hidden":false}]

```

---

<div class="post-metadata">

**Author:** ![shrickus](https://sea2.discourse-cdn.com/flex026/user_avatar/discourse.nodered.org/shrickus/32/517_2.png) [@shrickus](https://discourse.nodered.org/u/shrickus)\
**Post date:** [22 February 2024 17:58 UTC](https://discourse.nodered.org/t/ui-template-edit-msg-payload-then-output/85694/8 "2024-02-22T17:58:09Z")

</div>

Yep, I do this as well... so I guess my question is more meant to open a dialog around the best way to capture these ad-hoc samples into a re-usable sample library.

> [@E1cid](#):
>
> I do tend to keep copies of them locally. Maybe I should add then to my git, I am pretty bad at doing that.

Not pointing fingers here, because I do the same thing! I have all of these great (imo) flow samples running... well, somewhere... on one of my dozens of node-red installs locally or in the cloud. Seems there is never enough time to actually organize them and put the finishing documentation on them. A year later I have trouble finding them -- I guess I was hoping others have worked out a better way to manage their flows (to supplement the flows library).

---

<div class="post-metadata">

**Author:** ![E1cid](https://sea2.discourse-cdn.com/flex026/user_avatar/discourse.nodered.org/e1cid/32/77971_2.png) [@E1cid](https://discourse.nodered.org/u/E1cid)\
**Post date:** [22 February 2024 18:02 UTC](https://discourse.nodered.org/t/ui-template-edit-msg-payload-then-output/85694/9 "2024-02-22T18:02:26Z")

</div>

> [@shrickus](#):
>
> so I guess my question is more meant to open a dialog around the best way to capture these ad-hoc samples into a re-usable sample library.

Lets not hijack this thread, I think it best to open that question up on its own topic.

---

<div class="post-metadata">

**Author:** ![system](https://us1.discourse-cdn.com/flex026/uploads/nodered/original/1X/d073cd938eafa2e558d7c2cd59003b3ef4963033.png) [@system](https://discourse.nodered.org/u/system)\
**Post date:** [23 March 2024 18:03 UTC](https://discourse.nodered.org/t/ui-template-edit-msg-payload-then-output/85694/10 "2024-03-23T18:03:20Z")

</div>

This topic was automatically closed 30 days after the last reply. New replies are no longer allowed.
