# Node-red-contrib-ui-svg create table by input message

**URL:** https://discourse.nodered.org/t/node-red-contrib-ui-svg-create-table-by-input-message/51004
**Category:** General
**Created:** [14 September 2021 10:04 UTC](https://discourse.nodered.org/t/node-red-contrib-ui-svg-create-table-by-input-message/51004 "2021-09-14T10:04:29Z")
**Posts on this page:** 12
**Page:** 1

<div class="post-metadata">

### Author: ![samuelbras](https://avatars.discourse-cdn.com/v4/letter/s/74df32/32.png) [@samuelbras](https://discourse.nodered.org/u/samuelbras)
#### Post date: [14 September 2021 10:04 UTC](https://discourse.nodered.org/t/node-red-contrib-ui-svg-create-table-by-input-message/51004/1 "2021-09-14T10:04:29Z")

</div>

Good Morning.  
I need to organize the goals in a table, and mark goals made and goals left to do.  
Is there any way to create a table with the goals, without being everything manually?

![image](https://us1.discourse-cdn.com/flex026/uploads/nodered/original/3X/3/7/37821d8ac0a099ef47b1b5b75bff48b7a5922152.png)

I get the task by input. Is there any way to put them in an automatically generated table?

---

<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: [14 September 2021 10:28 UTC](https://discourse.nodered.org/t/node-red-contrib-ui-svg-create-table-by-input-message/51004/2 "2021-09-14T10:28:00Z")

</div>

Ui-Table is certainly the first you should take a look at

> **[node-red-node-ui-table](https://flows.nodered.org/node/node-red-node-ui-table)**
>
> Table UI widget node for Node-RED Dashboard

---

<div class="post-metadata">

### Author: ![samuelbras](https://avatars.discourse-cdn.com/v4/letter/s/74df32/32.png) [@samuelbras](https://discourse.nodered.org/u/samuelbras)
#### Post date: [14 September 2021 11:15 UTC](https://discourse.nodered.org/t/node-red-contrib-ui-svg-create-table-by-input-message/51004/3 "2021-09-14T11:15:08Z")

</div>

but I need to integrate it inside the Node-red-contrib-ui-svg dashbord

---

<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: [14 September 2021 11:23 UTC](https://discourse.nodered.org/t/node-red-contrib-ui-svg-create-table-by-input-message/51004/4 "2021-09-14T11:23:24Z")

</div>

SVG doesn't have a table type.

Read this thread to understand your options....

"Create a table in SVG - Stack Overflow" [javascript - Create a table in SVG - Stack Overflow](https://stackoverflow.com/questions/6987005/create-a-table-in-svg)

---

<div class="post-metadata">

### Author: ![jbudd](https://avatars.discourse-cdn.com/v4/letter/j/5f8ce5/32.png) [@jbudd](https://discourse.nodered.org/u/jbudd)
#### Post date: [14 September 2021 11:29 UTC](https://discourse.nodered.org/t/node-red-contrib-ui-svg-create-table-by-input-message/51004/5 "2021-09-14T11:29:33Z")

</div>

Have you installed the core dashboard nodes (node-red-dashboard)?

---

<div class="post-metadata">

### Author: ![BartButenaers](https://sea2.discourse-cdn.com/flex026/user_avatar/discourse.nodered.org/bartbutenaers/32/10476_2.png) [@BartButenaers](https://discourse.nodered.org/u/BartButenaers)
#### Post date: [14 September 2021 18:49 UTC](https://discourse.nodered.org/t/node-red-contrib-ui-svg-create-table-by-input-message/51004/6 "2021-09-14T18:49:39Z")

</div>

> [@samuelbras](#):
>
> but I need to integrate it inside the Node-red-contrib-ui-svg dashbord

Hi @samuelbras,  
So I assume this table is surrounded by other shapes, and is part of a big drawing? Does it contain a lot rows? Because I am not sure how it will behave/look like when you have a larger table, that doesn't fit on the screen (and scrollbars are needed).

I don't think there is anything automatic available in SVG to accomplish this. Some ideas:

1. The most automatic pure SVG way of working, seems to me that you apply a fill pattern on a shape. Like a [grid](https://stackoverflow.com/questions/14208673/how-to-draw-grid-using-html5-and-canvas-or-svg), but with larger cells. Then you have your lines already out of the box, but of course you still need to position your texts at the correct coordinates. But absolutely not sure whether this is a good way to go...

2. As @Steve-Mcl already explained, you can embed a standard html table inside an SVG drawing. The values of that foreign table element can be filled via an input msg (see [here](https://github.com/bartbutenaers/node-red-contrib-ui-svg/blob/9a6e0d40d808e8e38c7c68c54ceeea8a05453abb/docs/msg_control.md#update-input-value-via-msg)). And [here](https://discourse.nodered.org/t/node-red-contrib-ui-svg-experimenting-with-foreign-elements/36777) you can find some of my experiments with foreign objects in the SVG node, although I have never used a table as foreign object myself ...

3. And if you want to do it in pure SVG, you can also write some Javascript to calculate all the shapes to draw a table. But seems a lot of work to me. If you want to go that way, you might find some examples on the web to get you started (e.g. [here](https://tink.uk/accessible-svg-tables/)).

So I think you first need to decide which way you want to go. Personally I think the html table inside the foreign object might be most automatic way of working. Because the html table component will do a lot of the work for you.

We don't know how the entire SVG drawing will look like, or how the table will be part of it (e.g. scrollbar when the table grows). So I'm afraid you are the only that can determine which will be the best way to go...

Bart

---

<div class="post-metadata">

### Author: ![samuelbras](https://avatars.discourse-cdn.com/v4/letter/s/74df32/32.png) [@samuelbras](https://discourse.nodered.org/u/samuelbras)
#### Post date: [16 September 2021 09:47 UTC](https://discourse.nodered.org/t/node-red-contrib-ui-svg-create-table-by-input-message/51004/7 "2021-09-16T09:47:12Z")

</div>

Hi @BartButenaers

Yes, the table is integrated in a SVG Group inside a whole SVG.

For the scrollbars I have found a peace of code that add scrollbar in svg.  
Now, for this propose I have made in pure SVG by input message. I have some work but I think that is solved for now.

thank you all for the support

Best regards

Samuel Brás

---

<div class="post-metadata">

### Author: ![BartButenaers](https://sea2.discourse-cdn.com/flex026/user_avatar/discourse.nodered.org/bartbutenaers/32/10476_2.png) [@BartButenaers](https://discourse.nodered.org/u/BartButenaers)
#### Post date: [16 September 2021 21:20 UTC](https://discourse.nodered.org/t/node-red-contrib-ui-svg-create-table-by-input-message/51004/8 "2021-09-16T21:20:05Z")

</div>

Hi @samuelbras,  
You are welcome! Nice to hear that you are managing to get it solved.

If you should afterwards have a small (simplified) example flow to demonstrate it, it would be nice if you would like to share it with us. Only a simple small table that you can update via a simple input message.  
To be honest, I am very curious now how something like that would look like.  
Never seen something like that before ...

Thanks!  
Bart

---

<div class="post-metadata">

### Author: ![samuelbras](https://avatars.discourse-cdn.com/v4/letter/s/74df32/32.png) [@samuelbras](https://discourse.nodered.org/u/samuelbras)
#### Post date: [6 October 2021 13:22 UTC](https://discourse.nodered.org/t/node-red-contrib-ui-svg-create-table-by-input-message/51004/9 "2021-10-06T13:22:39Z")

</div>

Hi @BartButenaers

I have prepared a simple sample, that solve my case.

the input message that I recive is somting like

```auto
   { "grid": [
        {
            "id": 100,
            "grid_item": "Line 1 text",
        },
        {
            "id": 110,
            "grid_item": "Line 2 text",
        },
        {
            "id": 120,
            "grid_item": "Line 3 text",
        },
        {
            "id": 130,
            "grid_item": "Line 4 text",
        },
        {
            "id": 140,
            "grid_item": "Line 5 text",
        },
        {
            "id": 150,
            "grid_item": "Line 6 text",
        }
    ]
	}

```

and the function that recive is like

```auto

var addX = 96;
var countElements=0;
msg.payload = [];

for (let i = 0; i < gridLines; i++) {

positionId = Order[i].id;
next = Order[i].next;
previous = Order[i].previous;

lineText = Order[i].grid_item;

var positionX = 64 + (addX*i);
var positionXLine = 100 + (addX*i);

var elementgroup = {
    "command" : "add_element",
    "elementType" : "group",
    "elementId" : "group"+positionId,
    "parentElementId" : "scrollgroup",
    "elementAttributes":{
        "next": next,
        "previous": previous
    }
};
msg.payload[countElements]= elementgroup;
countElements++;

var elementStep = {
    "command" : "add_element",
    "elementType" : "text",
    "elementId" : "topicPos"+positionId,
    "parentElementId" : "group"+positionId,
    "elementAttributes":{
        "class": "cls-7 " +positionId,
        "transform":"translate(72 " + positionX +")"
    },
    "textContent": i+1 + " / " + gridLines
};
msg.payload[countElements]= elementStep;
countElements++;

var elementDesc ="";

    elementDesc = {
        "command" : "add_element",
        "elementType" : "text",
        "elementId" : "topicDesc"+positionId,
        "parentElementId" : "group"+positionId,
        "elementAttributes":{
            "class": "cls-7 "+ positionId,
            "transform":"translate(171 " + positionX +")"
        },
        "textContent": lineText
    };

msg.payload[countElements]= elementDesc;
countElements++

var elementLine = {
    "command" : "add_element",
    "elementType" : "line",
    "elementId" : "line"+positionId,
    "parentElementId" : "group"+positionId,
    "elementAttributes":{
        "class": "cls-objectiveSeparator "+ positionId,
        "x2": "1600",
        "transform":"translate(20 " + positionXLine +")"
    }
};
countElements++;
}

```

It has some problems, like if the text in the grid has 2 rows or more.  
But for now it solve the problem.

---

<div class="post-metadata">

### Author: ![BartButenaers](https://sea2.discourse-cdn.com/flex026/user_avatar/discourse.nodered.org/bartbutenaers/32/10476_2.png) [@BartButenaers](https://discourse.nodered.org/u/BartButenaers)
#### Post date: [6 October 2021 19:02 UTC](https://discourse.nodered.org/t/node-red-contrib-ui-svg-create-table-by-input-message/51004/10 "2021-10-06T19:02:40Z")

</div>

> [@samuelbras](#):
>
> I have prepared a simple sample

Hey @samuelbras,  
Thanks for sharing your solution, so others can benefit from it !!  
Bart

---

<div class="post-metadata">

### Author: ![BartButenaers](https://sea2.discourse-cdn.com/flex026/user_avatar/discourse.nodered.org/bartbutenaers/32/10476_2.png) [@BartButenaers](https://discourse.nodered.org/u/BartButenaers)
#### Post date: [6 October 2021 21:39 UTC](https://discourse.nodered.org/t/node-red-contrib-ui-svg-create-table-by-input-message/51004/11 "2021-10-06T21:39:12Z")

</div>

@samuelbras,  
I was wondering whether it would have been easier to add a HTML table as a _ **foreign element** _ inside the SVG drawing. So I am now talking about option 2 mentioned above.

Seemed tonight that this was _ **not** _ possible, because the `add_element` command only allowed to create SVG elements (which have their own namespace). I have added a _ **fix** _ on Github to allow non-SVG elements to be created, by adding a `foreignElement=true` to the input message. That allows to create standard HTML elements, like e.g. a `<tr>` element for a table row.

The example flow contains [this](https://www.svgrepo.com/svg/134455/board) SVG drawing of a board, and I have added a standard HTML table as a foreign object to that SVG drawing:

```auto
<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0" y="0" height="263" viewBox="0 0 263 263" width="263">
  <g>
    <path d="M257.333,25.497h-32.867c0.124-0.48,0.196-0.98,0.196-1.499c0-3.313-2.687-6-6-6h-46.51
		c0.012-0.161,0.025-0.321,0.025-0.485c0-3.581-2.904-6.485-6.485-6.485h-68.05c-3.581,0-6.485,2.903-6.485,6.485
		c0,0.164,0.013,0.324,0.025,0.485h-46.51c-3.313,0-6,2.687-6,6c0,0.518,0.073,1.019,0.196,1.499H6c-3.314,0-6,2.686-6,6v148.492
		c0,3.313,2.686,6,6,6h115.926l-34.101,57.244c-1.696,2.847-0.763,6.53,2.084,8.226c2.848,1.696,6.53,0.763,8.226-2.084
		l27.532-46.217v33.019c0,3.313,2.687,6,6,6s6-2.687,6-6v-33.019l27.532,46.217c1.123,1.884,3.116,2.93,5.161,2.93
		c1.044,0,2.103-0.273,3.065-0.846c2.847-1.696,3.78-5.378,2.084-8.226l-34.101-57.244h115.926c3.314,0,6-2.687,6-6V31.497
		C263.333,28.183,260.647,25.497,257.333,25.497z M251.333,173.989H12V37.497h239.333V173.989z" />
  </g>
  <foreignObject x="30" y="50" width="200" height="110">
    <table style="width: 100%; border:2px solid;text-align:left">
      <colgroup>
        <col span="1" style="width: 70%;">
        <col span="1" style="width: 30%;">
      </colgroup>
      <tbody id="mytable">
        <tr>
          <th style="font-weight: bolder;text-decoration: underline">Room</th>
          <th style="font-weight: bolder;text-decoration: underline">°C</th>
        </tr>
        <tr>
          <td>Kitchen</td>
          <td>21</td>
        </tr>
      </tbody>
    </table>
  </foreignObject>
</svg>

```

Now we can add dynamically a table row, by injecting a message that creates a `tr` HTML element as a child of the table body (with id _"mytable"_). The table row (tr) contains two table cells (td):

```auto
{
    "command": "add_element",
    "elementType": "tr",
    "textContent": "<td>Bathroom</td><td>22</td>",
    "parentElementId": "mytable",
    "foreignElement": true
}

```

Which results in this:

![svg_table](https://us1.discourse-cdn.com/flex026/uploads/nodered/original/3X/c/0/c021d47f3c2329d9dea59577e68e8c8ce7a305f8.gif)

Here is the entire flow:

![image](https://us1.discourse-cdn.com/flex026/uploads/nodered/original/3X/0/9/0946932af0956287871b1a263cce17d6a9d70a3f.png)

```auto
[{"id":"ac37cc973bbb46fe","type":"ui_svg_graphics","z":"3f01ab2a1bf97f25","group":"3ce32370.c60f1c","order":11,"width":"18","height":"10","svgString":"<svg xmlns=\"http://www.w3.org/2000/svg\" xmlns:xlink=\"http://www.w3.org/1999/xlink\" x=\"0\" y=\"0\" height=\"263\" viewBox=\"0 0 263 263\" width=\"263\">\n <g>\n <path d=\"M257.333,25.497h-32.867c0.124-0.48,0.196-0.98,0.196-1.499c0-3.313-2.687-6-6-6h-46.51\n\t\tc0.012-0.161,0.025-0.321,0.025-0.485c0-3.581-2.904-6.485-6.485-6.485h-68.05c-3.581,0-6.485,2.903-6.485,6.485\n\t\tc0,0.164,0.013,0.324,0.025,0.485h-46.51c-3.313,0-6,2.687-6,6c0,0.518,0.073,1.019,0.196,1.499H6c-3.314,0-6,2.686-6,6v148.492\n\t\tc0,3.313,2.686,6,6,6h115.926l-34.101,57.244c-1.696,2.847-0.763,6.53,2.084,8.226c2.848,1.696,6.53,0.763,8.226-2.084\n\t\tl27.532-46.217v33.019c0,3.313,2.687,6,6,6s6-2.687,6-6v-33.019l27.532,46.217c1.123,1.884,3.116,2.93,5.161,2.93\n\t\tc1.044,0,2.103-0.273,3.065-0.846c2.847-1.696,3.78-5.378,2.084-8.226l-34.101-57.244h115.926c3.314,0,6-2.687,6-6V31.497\n\t\tC263.333,28.183,260.647,25.497,257.333,25.497z M251.333,173.989H12V37.497h239.333V173.989z\" />\n </g>\n <foreignObject x=\"30\" y=\"50\" width=\"200\" height=\"110\">\n <table style=\"width: 100%; border:2px solid;text-align:left\">\n <colgroup>\n <col span=\"1\" style=\"width: 70%;\">\n <col span=\"1\" style=\"width: 30%;\">\n </colgroup>\n <tbody id=\"mytable\">\n <tr>\n <th style=\"font-weight: bolder;text-decoration: underline\">Room</th>\n <th style=\"font-weight: bolder;text-decoration: underline\">°C</th>\n </tr>\n <tr>\n <td>Kitchen</td>\n <td>21</td>\n </tr>\n </tbody>\n </table>\n </foreignObject>\n</svg>","clickableShapes":[],"javascriptHandlers":[],"smilAnimations":[],"bindings":[],"showCoordinates":false,"autoFormatAfterEdit":false,"showBrowserErrors":true,"showBrowserEvents":true,"enableJsDebugging":false,"sendMsgWhenLoaded":false,"noClickWhenDblClick":false,"outputField":"payload","editorUrl":"//drawsvg.org/drawsvg.html","directory":"","panning":"disabled","zooming":"disabled","panOnlyWhenZoomed":false,"doubleClickZoomEnabled":false,"mouseWheelZoomEnabled":false,"dblClickZoomPercentage":150,"name":"","x":660,"y":80,"wires":[[]]},{"id":"41fc31c058631fe9","type":"inject","z":"3f01ab2a1bf97f25","name":"Add table row","props":[{"p":"payload"}],"repeat":"","crontab":"","once":false,"onceDelay":0.1,"topic":"","payload":"{\"command\":\"add_element\",\"elementType\":\"tr\",\"textContent\":\"<td>Bathroom</td><td>22</td>\",\"parentElementId\":\"mytable\",\"foreignElement\":true}","payloadType":"json","x":430,"y":80,"wires":[["ac37cc973bbb46fe"]]},{"id":"3ce32370.c60f1c","type":"ui_group","name":"Demo","tab":"d74bbed4.c2cfb","order":2,"disp":false,"width":"18","collapse":false},{"id":"d74bbed4.c2cfb","type":"ui_tab","name":"Demo","icon":"dashboard","order":1,"disabled":false,"hidden":false}]

```

Note that I quickly created this example flow, and I can improved a lot: scrollbars, fixed headers during scrolling, fixed number of visible rows ... So if anybody wants to improve the example flow and share it here, that would be nice!

P.S. The fix is not available on NPM yet. So if you want to test this, you need to install the fixed svg node directly from Github using this command (from within your .node-red folder):

```auto
npm install bartbutenaers/node-red-contrib-ui-svg

```

---

<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: [5 December 2021 21:39 UTC](https://discourse.nodered.org/t/node-red-contrib-ui-svg-create-table-by-input-message/51004/12 "2021-12-05T21:39:40Z")

</div>

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