# Ui-table selection callback

**URL:** <https://discourse.nodered.org/t/ui-table-selection-callback/47861>\
**Category:** Dashboard\
**Created:** [30 June 2021 18:24 UTC](https://discourse.nodered.org/t/ui-table-selection-callback/47861 "2021-06-30T18:24:29Z")\
**Posts on this page:** 15\
**Page:** 1

<div class="post-metadata">

**Author:** ![rogerjames99](https://sea2.discourse-cdn.com/flex026/user_avatar/discourse.nodered.org/rogerjames99/32/25201_2.png) [@rogerjames99](https://discourse.nodered.org/u/rogerjames99)\
**Post date:** [30 June 2021 18:24 UTC](https://discourse.nodered.org/t/ui-table-selection-callback/47861/1 "2021-06-30T18:24:30Z")

</div>

I am trying to implement a callback to track the currently selected table row.

Here is my code.

```auto
msg.ui_control = {
    tabulator: {
        // This callback saves the current selected row
        rowSelected:function(row) {
            //row - row component for the selected row
            //flow.set('currentSelection', row)
            console.log('Yippee')
            //var newMessage = {
            // 'topic': this.config.topic,
            // 'ui_control': {
            // 'callback':'rowSelected',
            // 'row': row
            // }
            //}
            //this.send([undefined, newmessage])
        },
        // This callback is triggered when ever the table contents change
        dataChanged:function(data) {
            //data - the updated table data
        },
        "columns": [
            {
                "title": "Torque",
                "field": "torque",
                "editor": "number",
                "editorParams": { "step": 0.1}
            },
            {
                "title": "Duration",
                "field": "duration",
                "editor": "number"
            }
        ],
        "selectable":true,
        "layout": "fitColumns",
        "tooltips":true, //show tool tips on cells
        "history":true, //allow undo and redo actions on the table
        "pagination":"local", //paginate the data
        "paginationSize":14, //allow 7 rows per page of data
        "movableRows": true,
        "height":"100%",
        "data": [
            {
            "torque": 20,
            "duration": 1000
            },{
            "torque": 1.5,
            "duration": 100
            },{
            "torque": 10,
            "duration": 1000
            },{
            "torque": 30,
            "duration": 1000
            },{
            "torque": 40,
            "duration": 1000
            },{
            "torque": 50,
            "duration": 1000
            }
        ]
    }
}
// Add an empty row to force header to be displayed

msg.payload = [{"command": "addRow"}]

return msg;

```

I never see the console.log("Yippee") in the node red journal.

```auto
Jun 30 19:18:08 dragon Node-RED[7255]: 30 Jun 19:18:08 - [info] Starting flows
Jun 30 19:18:08 dragon Node-RED[7255]: 30 Jun 19:18:08 - [debug] red/nodes/flows.start : starting flow : global
Jun 30 19:18:08 dragon Node-RED[7255]: 30 Jun 19:18:08 - [debug] red/nodes/flows.start : starting flow : 76e403d6.61e914
Jun 30 19:18:08 dragon Node-RED[7255]: 30 Jun 19:18:08 - [info] Started flows

```

That is all I get.

Any help gratefully received. I have looked at the examples and forum threads.  
But I must be missing something

---

<div class="post-metadata">

**Author:** ![rogerjames99](https://sea2.discourse-cdn.com/flex026/user_avatar/discourse.nodered.org/rogerjames99/32/25201_2.png) [@rogerjames99](https://discourse.nodered.org/u/rogerjames99)\
**Post date:** [1 July 2021 08:55 UTC](https://discourse.nodered.org/t/ui-table-selection-callback/47861/2 "2021-07-01T08:55:22Z")

</div>

I think my mistake may be having the value of the rowSelected object as function type not a string type. Can anyone give me a definitive answer or pointer on this?

My code now looks like this.

```auto
msg.ui_control = {
    tabulator: {
        // This callback saves the current selected row
        rowSelected:"function(row) {"+
            "flow.set('currentSelection', row); "+
            "console.log('Yippee'); "+
            "var newMessage = { "+
                "'topic': this.config.topic, "+
                "'ui_control': { "+
                    "'callback':'rowSelected', "+
                    "'row': row "+
                "}"+
            "}"+
            "this.send([undefined, newmessage])"+
        "}",
        // This callback is triggered when ever the table contents change
        dataChanged:function(data) {
            //data - the updated table data
        },
        "columns": [
            {
                "title": "Torque",
                "field": "torque",
                "editor": "number",
                "editorParams": { "step": 0.1}
            },
            {
                "title": "Duration",
                "field": "duration",
                "editor": "number"
            }
        ],
        "selectable":true,
        "layout": "fitColumns",
        "tooltips":true, //show tool tips on cells
        "history":true, //allow undo and redo actions on the table
        "pagination":"local", //paginate the data
        "paginationSize":14, //allow 7 rows per page of data
        "movableRows": true,
        "height":"100%",
        "data": [
            {
            "torque": 20,
            "duration": 1000
            },{
            "torque": 1.5,
            "duration": 100
            },{
            "torque": 10,
            "duration": 1000
            },{
            "torque": 30,
            "duration": 1000
            },{
            "torque": 40,
            "duration": 1000
            },{
            "torque": 50,
            "duration": 1000
            }
        ]
    }
}
// Add an empty row to force header to be displayed

msg.payload = [{"command": "addRow"}]

return msg;

```

This deploys Ok, but the table is empty with only the header showing. I have lost the row data for some reason.

Thanks

---

<div class="post-metadata">

**Author:** ![rogerjames99](https://sea2.discourse-cdn.com/flex026/user_avatar/discourse.nodered.org/rogerjames99/32/25201_2.png) [@rogerjames99](https://discourse.nodered.org/u/rogerjames99)\
**Post date:** [1 July 2021 09:09 UTC](https://discourse.nodered.org/t/ui-table-selection-callback/47861/3 "2021-07-01T09:09:17Z")

</div>

The browser console shows this this

```auto
10:05:28.318 ui-table message arrived: <unavailable> app.min.js line 598 > eval:86:37
10:05:28.319 ui-table msg: <unavailable> app.min.js line 598 > eval:88:37

```

I have no idea whether this good or bad.

---

<div class="post-metadata">

**Author:** ![rogerjames99](https://sea2.discourse-cdn.com/flex026/user_avatar/discourse.nodered.org/rogerjames99/32/25201_2.png) [@rogerjames99](https://discourse.nodered.org/u/rogerjames99)\
**Post date:** [3 July 2021 23:54 UTC](https://discourse.nodered.org/t/ui-table-selection-callback/47861/4 "2021-07-03T23:54:57Z")

</div>

I have got things narrowed down a bit more. My latest version of the flow demonstrates the columnMoved callback working as expected. But the rowSelectionChanged callback causing a "InternalError: too much recursion". The rowSelected callback never fires. I suspect the rowSelection column formatter has something to do with this.

This is the latest table setup node

```auto
[{"id":"845329d3.eb6ed","type":"change","z":"76e403d6.61e914","name":"Setup Tabulator","rules":[{"t":"set","p":"ui_control","pt":"msg","to":"{\"tabulator\":{\"columnMoved\":\"function(column, columns){ var newColumns=[]; columns.forEach(function (column) { newColumns.push({'field': column._column.field}); }); this.send({topic:this.config.topic,ui_control:{callback:'columnMoved',columns:newColumns}}); }\",\"rowSelected\":\"function(row_selected){ this.send({topic:this.config.topic,ui_control:{'callback':'rowSelected','row':row_selected}}); }\",\"rowSelectionChanged\":\"function(data, rows){var newData=[]; data.forEach(function(data){newData.push(data);}); var newRows=[]; rows.forEach(function(row){newRows.push(row);}); this.send({topic:this.config.topic,ui_control:{callback:'rowSelectionChanged', data:newData, rows:newRows}});}\",\"layout\":\"fitColumns\",\"selectable\":1,\"movableColumns\":true,\"columns\":[{\"formatter\":\"rowSelection\",\"align\":\"center\",\"width\":\"2%\",\"headerSort\":false},{\"title\":\"Torque\",\"field\":\"torque\",\"editor\":\"number\",\"editorParams\":{\"step\":0.1}},{\"title\":\"Duration\",\"field\":\"duration\",\"editor\":\"number\"}]},\"customHeight\":12}","tot":"json"},{"t":"set","p":"payload","pt":"msg","to":"[{\"torque\":1,\"duration\":10},{\"torque\":1,\"duration\":10},{\"torque\":1,\"duration\":10},{\"torque\":1,\"duration\":10},{\"torque\":1,\"duration\":10},{\"torque\":1,\"duration\":10},{\"torque\":1,\"duration\":10},{\"torque\":1,\"duration\":10},{\"torque\":1,\"duration\":10},{\"torque\":1,\"duration\":10}]","tot":"json"}],"action":"","property":"","from":"","to":"","reg":false,"x":440,"y":100,"wires":[["b0495229.d891d8","840cb515.88f298"]]}]

```

Here is the the overall flow

```auto
[{"id":"76e403d6.61e914","type":"tab","label":"Sandpit","disabled":false,"info":""},{"id":"840cb515.88f298","type":"ui_table","z":"76e403d6.61e914","group":"880623ea.2d0768","name":"tabulator","order":0,"width":"5","height":"10","columns":[],"outputs":1,"cts":true,"x":680,"y":100,"wires":[["df0037a9.300af8"]]},{"id":"3721ea12.95402e","type":"inject","z":"76e403d6.61e914","name":"","props":[{"p":"payload"}],"repeat":"","crontab":"","once":true,"onceDelay":0.1,"topic":"","payload":"","payloadType":"str","x":210,"y":100,"wires":[["845329d3.eb6ed"]]},{"id":"b0495229.d891d8","type":"debug","z":"76e403d6.61e914","name":"table input sandpit","active":true,"tosidebar":true,"console":false,"tostatus":false,"complete":"true","targetType":"full","statusVal":"","statusType":"auto","x":730,"y":20,"wires":[]},{"id":"df0037a9.300af8","type":"debug","z":"76e403d6.61e914","name":"table output sandpit","active":true,"tosidebar":true,"console":false,"tostatus":false,"complete":"true","targetType":"full","statusVal":"","statusType":"auto","x":910,"y":100,"wires":[]},{"id":"a09ac705.964108","type":"function","z":"76e403d6.61e914","name":"Dummy function for verifying callback Javascript","func":"// I use this editor to write callback functions and check that the Javascript is valid.\n// I then compress the function onto a single line and then use the contents of the line after\n// the equals sign as a string value for value of the relevant callback property in the tabulator object.\n\n// This is line is for the columnMoved callback\n// \"function(column, columns){ var newColumns=[]; columns.forEach(function (column) { newColumns.push({'field': column._column.field}); }); this.send({topic:this.config.topic,ui_control:{callback:'columnMoved',columns:newColumns}}); }\"\nvar columnMoved = function(column, columns){ var newColumns=[]; columns.forEach(function (column) { newColumns.push({'field': column._column.field}); }); this.send({topic:this.config.topic,ui_control:{callback:'columnMoved',columns:newColumns}}); }\n\n// This line is for the row SelectedCallback\n// \"function(row_selected){ this.send({topic:this.config.topic,ui_control:{callback:'rowSelected',row:row_selected}}); }\"\nvar rowSelected = function(row_selected){ this.send({topic:this.config.topic,ui_control:{callback:'rowSelected',row:row_selected}}); }// This line is for the row SelectedCallback\n\n// This line is for the row SelectedCallback\n// \"function(data, rows){ this.send({topic:this.config.topic,ui_control:{callback:'rowSelectionChanged', 'rows':rows, 'data':data}});}\"\nvar rowSelectionChanged = function(data, rows){console.log(`rowSelectionChanged triggered - data ${JSON.stringify(data)} rows ${JSON.stringify(rows)}`); this.send({topic:this.config.topic,ui_control:{callback:'rowSelectionChanged', rows:rows, data:data}});}\n","outputs":1,"noerr":0,"initialize":"","finalize":"","libs":[],"x":740,"y":320,"wires":[[]]},{"id":"845329d3.eb6ed","type":"change","z":"76e403d6.61e914","name":"Setup Tabulator","rules":[{"t":"set","p":"ui_control","pt":"msg","to":"{\"tabulator\":{\"columnMoved\":\"function(column, columns){ var newColumns=[]; columns.forEach(function (column) { newColumns.push({'field': column._column.field}); }); this.send({topic:this.config.topic,ui_control:{callback:'columnMoved',columns:newColumns}}); }\",\"rowSelected\":\"function(row_selected){ this.send({topic:this.config.topic,ui_control:{'callback':'rowSelected','row':row_selected}}); }\",\"rowSelectionChanged\":\"function(data, rows){var newData=[]; data.forEach(function(data){newData.push(data);}); var newRows=[]; rows.forEach(function(row){newRows.push(row);}); this.send({topic:this.config.topic,ui_control:{callback:'rowSelectionChanged', data:newData, rows:newRows}});}\",\"layout\":\"fitColumns\",\"selectable\":1,\"movableColumns\":true,\"columns\":[{\"formatter\":\"rowSelection\",\"align\":\"center\",\"width\":\"2%\",\"headerSort\":false},{\"title\":\"Torque\",\"field\":\"torque\",\"editor\":\"number\",\"editorParams\":{\"step\":0.1}},{\"title\":\"Duration\",\"field\":\"duration\",\"editor\":\"number\"}]},\"customHeight\":12}","tot":"json"},{"t":"set","p":"payload","pt":"msg","to":"[{\"torque\":1,\"duration\":10},{\"torque\":1,\"duration\":10},{\"torque\":1,\"duration\":10},{\"torque\":1,\"duration\":10},{\"torque\":1,\"duration\":10},{\"torque\":1,\"duration\":10},{\"torque\":1,\"duration\":10},{\"torque\":1,\"duration\":10},{\"torque\":1,\"duration\":10},{\"torque\":1,\"duration\":10}]","tot":"json"}],"action":"","property":"","from":"","to":"","reg":false,"x":440,"y":100,"wires":[["b0495229.d891d8","840cb515.88f298"]]},{"id":"4df1d3a9.a99b54","type":"inject","z":"76e403d6.61e914","name":"inject","props":[],"repeat":"","crontab":"","once":false,"onceDelay":0.1,"topic":"","x":210,"y":160,"wires":[["5ba8034e.9b85ac"]]},{"id":"5ba8034e.9b85ac","type":"change","z":"76e403d6.61e914","name":"Setup from example","rules":[{"t":"set","p":"ui_control","pt":"msg","to":"{\"tabulator\":{\"columnMoved\":\"function(column, columns){ var newColumns=[]; columns.forEach(function (column) { newColumns.push({'field': column._column.field}); }); this.send({topic:this.config.topic,ui_control:{callback:'columnMoved',columns:newColumns}}); }\",\"layout\":\"fitColumns\",\"movableColumns\":true,\"groupBy\":\"\",\"columns\":[{\"title\":\"eTorque\",\"field\":\"torque\",\"editor\":\"number\",\"editorParams\":{\"step\":0.1}},{\"title\":\"eDuration\",\"field\":\"duration\",\"editor\":\"number\"}]},\"customHeight\":12}","tot":"json"},{"t":"set","p":"payload","pt":"msg","to":"{\"command\":\"addRow\"}","tot":"json"}],"action":"","property":"","from":"","to":"","reg":false,"x":420,"y":160,"wires":[["8b10457e.b151a"]]},{"id":"8b10457e.b151a","type":"debug","z":"76e403d6.61e914","name":"table input example sandpit","active":true,"tosidebar":true,"console":false,"tostatus":false,"complete":"true","targetType":"full","statusVal":"","statusType":"auto","x":740,"y":160,"wires":[]},{"id":"fff5c16e.a75478","type":"comment","z":"76e403d6.61e914","name":"N.B. Do not open the UI window until you have done the inject!!!!","info":"","x":350,"y":40,"wires":[]},{"id":"9f010854.96371","type":"ui_button","z":"76e403d6.61e914","name":"add_at_top","group":"8e465b51.c1e048","order":2,"width":0,"height":0,"passthru":false,"label":"Add at top","tooltip":"","color":"","bgcolor":"","icon":"","payload":"","payloadType":"str","topic":"topic","topicType":"msg","x":230,"y":440,"wires":[[]]},{"id":"616a46e7.0e817","type":"ui_button","z":"76e403d6.61e914","name":"add_at_bottom","group":"8e465b51.c1e048","order":3,"width":0,"height":0,"passthru":false,"label":"Add at bottom","tooltip":"","color":"","bgcolor":"","icon":"","payload":"","payloadType":"str","topic":"topic","topicType":"msg","x":240,"y":480,"wires":[[]]},{"id":"d0397e09.3bb17","type":"ui_button","z":"76e403d6.61e914","name":"run","group":"ff6f54a4.60fab","order":1,"width":0,"height":0,"passthru":false,"label":"Run","tooltip":"","color":"","bgcolor":"","icon":"","payload":"","payloadType":"str","topic":"topic","topicType":"msg","x":210,"y":260,"wires":[[]]},{"id":"84cd1d53.5d903","type":"ui_button","z":"76e403d6.61e914","name":"stop","group":"ff6f54a4.60fab","order":1,"width":0,"height":0,"passthru":false,"label":"Stop","tooltip":"","color":"","bgcolor":"","icon":"","payload":"","payloadType":"str","topic":"topic","topicType":"msg","x":210,"y":300,"wires":[[]]},{"id":"5d905b1.c3f26a4","type":"ui_button","z":"76e403d6.61e914","name":"step","group":"ff6f54a4.60fab","order":1,"width":0,"height":0,"passthru":false,"label":"Step","tooltip":"","color":"","bgcolor":"","icon":"","payload":"","payloadType":"str","topic":"topic","topicType":"msg","x":210,"y":340,"wires":[[]]},{"id":"aefaf.1db0c052","type":"ui_button","z":"76e403d6.61e914","name":"insert_above","group":"8e465b51.c1e048","order":3,"width":0,"height":0,"passthru":false,"label":"Insert above","tooltip":"","color":"","bgcolor":"","icon":"","payload":"","payloadType":"str","topic":"topic","topicType":"msg","x":230,"y":520,"wires":[[]]},{"id":"77c8a8b0.24515","type":"ui_button","z":"76e403d6.61e914","name":"insert_below","group":"8e465b51.c1e048","order":3,"width":0,"height":0,"passthru":false,"label":"Insert below","tooltip":"","color":"","bgcolor":"","icon":"","payload":"","payloadType":"str","topic":"topic","topicType":"msg","x":230,"y":560,"wires":[[]]},{"id":"93e7d240.91488","type":"ui_button","z":"76e403d6.61e914","name":"delete_selected","group":"8e465b51.c1e048","order":3,"width":0,"height":0,"passthru":false,"label":"Delete selected","tooltip":"","color":"","bgcolor":"","icon":"","payload":"","payloadType":"str","topic":"topic","topicType":"msg","x":240,"y":600,"wires":[[]]},{"id":"9b7e7d72.5f74e","type":"ui_button","z":"76e403d6.61e914","name":"delete_all","group":"8e465b51.c1e048","order":3,"width":0,"height":0,"passthru":false,"label":"Delete All","tooltip":"","color":"","bgcolor":"","icon":"","payload":"","payloadType":"str","topic":"topic","topicType":"msg","x":220,"y":640,"wires":[[]]},{"id":"880623ea.2d0768","type":"ui_group","name":"Programme","tab":"1d92acc1.5c9d03","order":2,"disp":true,"width":"5","collapse":false},{"id":"8e465b51.c1e048","type":"ui_group","name":"Edit","tab":"1d92acc1.5c9d03","order":3,"disp":true,"width":"3","collapse":false},{"id":"ff6f54a4.60fab","type":"ui_group","name":"Run","tab":"1d92acc1.5c9d03","order":1,"disp":true,"width":"3","collapse":false},{"id":"1d92acc1.5c9d03","type":"ui_tab","name":"Sandpit","icon":"dashboard","order":1,"disabled":false,"hidden":false}]

```

I seem to be whistling in the dark here. Once again any help gratefully received.

---

<div class="post-metadata">

**Author:** ![Christian-Me](https://sea2.discourse-cdn.com/flex026/user_avatar/discourse.nodered.org/christian-me/32/10774_2.png) [@Christian-Me](https://discourse.nodered.org/u/Christian-Me)\
**Post date:** [4 July 2021 14:41 UTC](https://discourse.nodered.org/t/ui-table-selection-callback/47861/5 "2021-07-04T14:41:38Z")

</div>

> [@rogerjames99](#):
>
> But the rowSelectionChanged callback causing a "InternalError: too much recursion".

Hi,  
Perhaps a [look into the docs](https://flows.nodered.org/node/node-red-node-ui-table) helps here:

> - use `this.send({})` to pass result to Node-RED. (to avoid a loopback add `ui_control.callback="someText"` )

```auto
this.send({topic: "anyTopic",payload:"anyPayload",ui_control: {callback:"myCallback"}});

```

It seams that you miss the `callback` property if you get the `too much recursion` error.  
For a deeper insight on callbacks perhaps take a look into example 6 and especially the debug node outputs.

On tip for coding the callbacks: I use a function node to code my callbacks (with basic syntax error checking) and then copy/paste into any node supporting typed inputs with JSON type support (like inject, change ore even buttons) and paste your code into the visual JSON editor tab doing most escaping of special characters for you.

Hope this helps. It isn't dark here 😉 but it is Summer and less timer to spend on the bench 🌞

---

<div class="post-metadata">

**Author:** ![Christian-Me](https://sea2.discourse-cdn.com/flex026/user_avatar/discourse.nodered.org/christian-me/32/10774_2.png) [@Christian-Me](https://discourse.nodered.org/u/Christian-Me)\
**Post date:** [4 July 2021 14:45 UTC](https://discourse.nodered.org/t/ui-table-selection-callback/47861/6 "2021-07-04T14:45:20Z")

</div>

> [@rogerjames99](#):
>
> I never see the console.log("Yippee") in the node red journal.

To see the `console.log()`output of callbacks you have to take a look into the **browser** console (developer tools) of your **dashboard** as the callback is executed there. Here you also find error messages if any.

---

<div class="post-metadata">

**Author:** ![rogerjames99](https://sea2.discourse-cdn.com/flex026/user_avatar/discourse.nodered.org/rogerjames99/32/25201_2.png) [@rogerjames99](https://discourse.nodered.org/u/rogerjames99)\
**Post date:** [4 July 2021 20:18 UTC](https://discourse.nodered.org/t/ui-table-selection-callback/47861/7 "2021-07-04T20:18:40Z")

</div>

Hi Chris,

Thanks for your responses.

I have been looking in the browser console as well as the node red systemd journal for rhe console.log messages.

Thanks for the tip about putting the callback code in a function node to check it. I picked that up from the examples and have been doing that. This is what my dummy node contains.

```auto
// I use this editor to write callback functions and check that the Javascript is valid.
// I then compress the function onto a single line and then use the contents of the line after
// the equals sign as a string value for value of the relevant callback property in the tabulator object.
// "columnMoved": "function(column, columns){ var newColumns=[]; columns.forEach(function (column) { newColumns.push({'field': column._column.field}); }); this.send({topic:this.config.topic,ui_control:{callback:'columnMoved',columns:newColumns}}); }",
// "rowSelected": "function(row_selected){ this.send({topic:this.config.topic,ui_control:{'callback':'rowSelected','row':row_selected}}); }",
// "rowSelectionChanged": "function(data, rows){var newData=[]; data.forEach(function(data){newData.push(data);}); var newRows=[]; rows.forEach(function(row){newRows.push(row);}); this.send({topic:this.config.topic,ui_control:{callback:'rowSelectionChanged', data:newData, rows:newRows}});}",

var columnMoved = function(column, columns) {
    var newColumns=[];
    columns.forEach( function (column) {
        newColumns.push({'field': column._column.field});
    });
    this.send({
        topic:this.config.topic,
        ui_control:{
            callback:'columnMoved',
            columns:newColumns
        }
    });
}

var rowSelected = function(row_selected) {
    this.send({
        topic:this.config.topic,
        ui_control:{
            'callback':'rowSelected',
            'row':row_selected            
        }
    });
}

var rowSelectionChanged = function(data, rows) {
    var newData=[];
    data.forEach( function (data) {
        newData.push(data);
    });
    var newRows=[];
    rows.forEach(function (row) {
        newRows.push(row);
    });
    this.send({
        topic:this.config.topic,
        ui_control:{
            callback:'rowSelectionChanged',
            data:newData,
            rows:newRows
        }
    });
}

```

I suspect that somewhere I am putting javascript instead of JSON or vice versa. I try to fully restart node red and the browser windows for each test, as I find that I sometimes end up running the previous version in the dashboard ui. I would be nice to find a way to clear the tabulator to default settings when the flow is restarted.

I have not looked in detail at example six. I will do that now.

Thank you for your excellent work on this and for putting up with my struggles. Go out and enjoy the summer, we have thunderstorms at the moment in the Lake District of Northwest England. It is raining buckets.

Roger

---

<div class="post-metadata">

**Author:** ![rogerjames99](https://sea2.discourse-cdn.com/flex026/user_avatar/discourse.nodered.org/rogerjames99/32/25201_2.png) [@rogerjames99](https://discourse.nodered.org/u/rogerjames99)\
**Post date:** [5 July 2021 11:02 UTC](https://discourse.nodered.org/t/ui-table-selection-callback/47861/8 "2021-07-05T11:02:46Z")

</div>

Ok,

Can anyone see the difference between these two functions?

```auto
// The this.send in this causes an excessive recursion failure
var rowSelectionChanged = function(data, rows) {
  var newData = [];
  data.forEach(function(data) {
    newData.push(data);
  });
  var newRows = [];
  rows.forEach(function(row) {
    newRows.push(row);
  });
  this.send({
    topic: this.config.topic,
    ui_control: {
      callback: 'rowSelectionChanged',
      data: newData,
      rows: newRows
    }
  });
}

// The this.send in this one does not.
columnMoved = function(column, columns) {
  var newColumns = [];
  columns.forEach(function(column) {
    newColumns.push({
      'field': column._column.field
    });
  });
  this.send({
    topic: this.config.topic,
    ui_control: {
      callback: 'columnMoved',
      columns: newColumns
    }
  });
}

```

I cannot. But maybe I have looked too often.

I have just noticed one. I am pushing an object reference rather than an object.  
I will check that out later.

Roger

---

<div class="post-metadata">

**Author:** ![zenofmud](https://sea2.discourse-cdn.com/flex026/user_avatar/discourse.nodered.org/zenofmud/32/316_2.png) [@zenofmud](https://discourse.nodered.org/u/zenofmud)\
**Post date:** [5 July 2021 11:41 UTC](https://discourse.nodered.org/t/ui-table-selection-callback/47861/9 "2021-07-05T11:41:39Z")

</div>

> columns.forEach(function(column) {

You have `columns` instead of ` column` At the start and the reverse at the end

---

<div class="post-metadata">

**Author:** ![Christian-Me](https://sea2.discourse-cdn.com/flex026/user_avatar/discourse.nodered.org/christian-me/32/10774_2.png) [@Christian-Me](https://discourse.nodered.org/u/Christian-Me)\
**Post date:** [5 July 2021 12:50 UTC](https://discourse.nodered.org/t/ui-table-selection-callback/47861/10 "2021-07-05T12:50:19Z")

</div>

I would not mess with the internals of the component objects (`_column`) as they might change in the future. Use the get / set functions instead. (there is a ton of useful methods available too)

```auto
var columnMoved = function(column, columns) {
  var newColumns = [];
  columns.forEach(function(column) {
    newColumns.push({
      'field': column.getField(),
      'width': column.getWidth()
    });
  });
  this.send({
    topic: this.config.topic,
    payload: newColumns,
    ui_control: {
      callback: 'columnMoved'
    }
  });
}

```

I added the width property for demonstration only (an object with only one property looks so lonely 😉  
You can put your payload outside the `ui_control` object too.

> **[Tabulator - Interactive JavaScript Tables](http://tabulator.info/docs/4.7/components#component-column)**
>
> Create interactive data tables in seconds with Tabulator. A lightweight, fully featured JavaScript table generation library.

---

<div class="post-metadata">

**Author:** ![rogerjames99](https://sea2.discourse-cdn.com/flex026/user_avatar/discourse.nodered.org/rogerjames99/32/25201_2.png) [@rogerjames99](https://discourse.nodered.org/u/rogerjames99)\
**Post date:** [5 July 2021 13:19 UTC](https://discourse.nodered.org/t/ui-table-selection-callback/47861/11 "2021-07-05T13:19:32Z")

</div>

Hold on a minute guys. It is the first function that does not work. The second is taken from example three. I do not need to use that one. I just used it as a template for for using this.send to send a ui\_control message to a ui\_table node.

Roger

---

<div class="post-metadata">

**Author:** ![Christian-Me](https://sea2.discourse-cdn.com/flex026/user_avatar/discourse.nodered.org/christian-me/32/10774_2.png) [@Christian-Me](https://discourse.nodered.org/u/Christian-Me)\
**Post date:** [5 July 2021 15:09 UTC](https://discourse.nodered.org/t/ui-table-selection-callback/47861/12 "2021-07-05T15:09:48Z")

</div>

Ok, I see - But same "problem" here. rows is an array of row component objects.

instead of `newRows.push(row);` use `newRows.push(row.getData());`

A component object can't be converted to a JSON object and sent from the UI to the backend. In the end your callback will probably send back the hole table when the selection changes. Perhaps cherry pick the data you really need.

BTW: Data gives you the data to the last selected row and can be sent directly. Rows gives you a array of row components if you have multiple selections enabled:

This might work:

```auto
var rowSelectionChanged = function(data, rows) {
  var selectedRows = [];
  rows.forEach(function(row) {
    selectedRows.push(row.getData());
  });
  this.send({
    topic: this.config.topic,
    payload: data,
    selectedRows: selectedRows,
    ui_control: {
      callback: 'rowSelectionChanged'
    }
  });
}

```

---

<div class="post-metadata">

**Author:** ![rogerjames99](https://sea2.discourse-cdn.com/flex026/user_avatar/discourse.nodered.org/rogerjames99/32/25201_2.png) [@rogerjames99](https://discourse.nodered.org/u/rogerjames99)\
**Post date:** [5 July 2021 15:19 UTC](https://discourse.nodered.org/t/ui-table-selection-callback/47861/13 "2021-07-05T15:19:14Z")

</div>

I was just typing the following when your reply came in !

"Ok I have now got rowSelected and rowSelectionChanged callbacks work. But only if I I do not send any properties in the message that include objects that have been passed into the callback function. I am going to try JSON.stringify on the objects I need."

I will now follow your suggestion. Many many thanks. I am embarrassed to admit how much time I have wasted looking at this. The table data I am working with is very small.

---

<div class="post-metadata">

**Author:** ![Christian-Me](https://sea2.discourse-cdn.com/flex026/user_avatar/discourse.nodered.org/christian-me/32/10774_2.png) [@Christian-Me](https://discourse.nodered.org/u/Christian-Me)\
**Post date:** [5 July 2021 15:28 UTC](https://discourse.nodered.org/t/ui-table-selection-callback/47861/14 "2021-07-05T15:28:53Z")

</div>

Don't forget that you might gain knowledge by try and error 😉  
JSON.stringify() might not work with component objects (as they includes methods=code not only data). This is what caused your original issue as this.send does exactly that.  
if you use a `console.log()`on your data you can investigate what type of data it is (and the methods you can use to access the data)

 ![image](https://us1.discourse-cdn.com/flex026/uploads/nodered/original/3X/e/8/e8a1b4444ac3bad178f08715d86f3c4b88a594e5.png)  
All properties starting with an \_ indicates data of a component and should not accessed directly.

---

<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:** [4 August 2021 15:28 UTC](https://discourse.nodered.org/t/ui-table-selection-callback/47861/15 "2021-08-04T15:28:59Z")

</div>

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