# Node-RED-UI Image Grid

**URL:** <https://discourse.nodered.org/t/node-red-ui-image-grid/47803>\
**Category:** Dashboard\
**Created:** [29 June 2021 17:19 UTC](https://discourse.nodered.org/t/node-red-ui-image-grid/47803 "2021-06-29T17:19:51Z")\
**Posts on this page:** 8\
**Page:** 1

<div class="post-metadata">

**Author:** ![qudek77](https://sea2.discourse-cdn.com/flex026/user_avatar/discourse.nodered.org/qudek77/32/44060_2.png) [@qudek77](https://discourse.nodered.org/u/qudek77)\
**Post date:** [29 June 2021 17:19 UTC](https://discourse.nodered.org/t/node-red-ui-image-grid/47803/1 "2021-06-29T17:19:51Z")

</div>

Hey guys,

Is there a way to have something like an image grid in the dashboard?

I have images of chess figures, and I would like them to arrange according to the data I am sending in the flow.

I tried with the ui-table node, it has an Image option, but for some reason, it doesn't display the image.

Does someone have an example of the usage of a ui-table node with images? If it works it would be great since the table is basically a 2D grid.

If there is a better way, please let me know.  
Thanks for the help.

This should be the end result:

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

---

<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:** [29 June 2021 18:37 UTC](https://discourse.nodered.org/t/node-red-ui-image-grid/47803/2 "2021-06-29T18:37:16Z")

</div>

I'd propose a UI template node with a table or grid of divs.

Give each cell a uniform ID or class (e.g. a1 ~ h8)

Then using something like msg.topic as the grid address and msg.payload as the image source.

---

<div class="post-metadata">

**Author:** ![qudek77](https://sea2.discourse-cdn.com/flex026/user_avatar/discourse.nodered.org/qudek77/32/44060_2.png) [@qudek77](https://discourse.nodered.org/u/qudek77)\
**Post date:** [4 July 2021 11:54 UTC](https://discourse.nodered.org/t/node-red-ui-image-grid/47803/4 "2021-07-04T11:54:53Z")

</div>

This is what I currently have:

Image in code:  
`<img src="data:image/png;base64,{{payload}}"style="width="500" height="500""/>`

template code:

```auto
<table>
  <tr>
    <td ng-bind-html="msg.payload" id = "A1"></td>
  </tr>
</table>

```

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

I'm not sure how to use ID/class and msg.topic with angular.

---

<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:** [4 July 2021 22:50 UTC](https://discourse.nodered.org/t/node-red-ui-image-grid/47803/5 "2021-07-04T22:50:52Z")

</div>

> [@qudek77](#):
>
> I'm not sure how to use ID/class and msg.topic with angular.

There is info in the side panel help on how to handle incoming `msg`s.

Here is something to get you moving...

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

**Demo flow...**

```auto
[{"id":"dac0c1824c37b7c7","type":"ui_template","z":"e78eac1c.8b9cf","group":"dce9e7a2.d20c78","name":"","order":1,"width":"9","height":"9","format":"<style>\n table.chess-board {\n border-spacing: 0px;\n border-width: 1px;\n }\n table.chess-board td {\n border: 1px solid black;\n padding: 0px;\n width: 50px;\n height: 50px;\n font-size: 30px;\n text-align: center;\n vertical-align: middle;\n }\n .chess-board td.light {\n background-color: ivory;\n }\n .chess-board td.dark {\n background-color: lightslategray;\n }\n \n</style>\n\n\n<table class=\"chess-board\">\n <tr class=\"a\">\n <td class=\"a1 light\"></td> <td class=\"a2 dark\"></td> <td class=\"a3 light\"></td> <td class=\"a4 dark\"></td> <td class=\"a5 light\"></td> <td class=\"a6 dark\"></td> <td class=\"a7 light\"></td> <td class=\"a8 dark\"></td>\n </tr>\n <tr class=\"b\">\n <td class=\"b1 dark\"></td> <td class=\"b2 light\"></td> <td class=\"b3 dark\"></td> <td class=\"b4 light\"></td> <td class=\"b5 dark\"></td> <td class=\"b6 light\"></td> <td class=\"b7 dark\"></td> <td class=\"b8 light\"></td>\n </tr>\n <tr class=\"c\">\n <td class=\"c1 light\"></td> <td class=\"c2 dark\"></td> <td class=\"c3 light\"></td> <td class=\"c4 dark\"></td> <td class=\"c5 light\"></td> <td class=\"c6 dark\"></td> <td class=\"c7 light\"></td> <td class=\"c8 dark\"></td>\n </tr>\n <tr class=\"d\">\n <td class=\"d1 dark\"></td> <td class=\"d2 light\"></td> <td class=\"d3 dark\"></td> <td class=\"d4 light\"></td> <td class=\"d5 dark\"></td> <td class=\"d6 light\"></td> <td class=\"d7 dark\"></td> <td class=\"d8 light\"></td>\n </tr>\n <tr class=\"e\">\n <td class=\"e1 light\"></td> <td class=\"e2 dark\"></td> <td class=\"e3 light\"></td> <td class=\"e4 dark\"></td> <td class=\"e5 light\"></td> <td class=\"e6 dark\"></td> <td class=\"e7 light\"></td> <td class=\"e8 dark\"></td>\n </tr>\n <tr class=\"f\">\n <td class=\"f1 dark\"></td> <td class=\"f2 light\"></td> <td class=\"f3 dark\"></td> <td class=\"f4 light\"></td> <td class=\"f5 dark\"></td> <td class=\"f6 light\"></td> <td class=\"f7 dark\"></td> <td class=\"f8 light\"></td>\n </tr>\n <tr class=\"g\">\n <td class=\"g1 light\"></td> <td class=\"g2 dark\"></td> <td class=\"g3 light\"></td> <td class=\"g4 dark\"></td> <td class=\"g5 light\"></td> <td class=\"g6 dark\"></td> <td class=\"g7 light\"></td> <td class=\"g8 dark\"></td>\n </tr>\n <tr class=\"h\">\n <td class=\"h1 dark\"></td> <td class=\"h2 light\"></td> <td class=\"h3 dark\"></td> <td class=\"h4 light\"></td> <td class=\"h5 dark\"></td> <td class=\"h6 light\"></td> <td class=\"h7 dark\"></td> <td class=\"h8 light\"></td>\n </tr>\n</table>\n\n\n<script type=\"text/javascript\">\n (function(scope) {\n const _scope = scope;\n scope.$watch('msg', function(msg) {\n if(msg && msg.topic && msg.payload) {\n const el = $(msg.topic); \n el.text(msg.payload);\n }\n });\n })(scope);\n</script>\n\n","storeOutMessages":true,"fwdInMessages":true,"resendOnRefresh":false,"templateScope":"local","className":"","x":1580,"y":300,"wires":[[]]},{"id":"a4a9f0052a91b6d6","type":"inject","z":"e78eac1c.8b9cf","name":"","props":[{"p":"payload"},{"p":"topic","vt":"str"}],"repeat":"","crontab":"","once":false,"onceDelay":0.1,"topic":".chess-board .a3","payload":"♗","payloadType":"str","x":1330,"y":220,"wires":[["dac0c1824c37b7c7"]]},{"id":"fa2b5b70eeb5bc8d","type":"inject","z":"e78eac1c.8b9cf","name":"","props":[{"p":"payload"},{"p":"topic","vt":"str"}],"repeat":"","crontab":"","once":false,"onceDelay":0.1,"topic":".chess-board .a1","payload":"♕","payloadType":"str","x":1330,"y":140,"wires":[["dac0c1824c37b7c7"]]},{"id":"2a602aba971e708f","type":"inject","z":"e78eac1c.8b9cf","name":"","props":[{"p":"payload"},{"p":"topic","vt":"str"}],"repeat":"","crontab":"","once":false,"onceDelay":0.1,"topic":".chess-board .a2","payload":"♘","payloadType":"str","x":1330,"y":180,"wires":[["dac0c1824c37b7c7"]]},{"id":"b784c50a1d976d51","type":"inject","z":"e78eac1c.8b9cf","name":"","props":[{"p":"payload"},{"p":"topic","vt":"str"}],"repeat":"","crontab":"","once":false,"onceDelay":0.1,"topic":".chess-board .h2","payload":"♞","payloadType":"str","x":1330,"y":380,"wires":[["dac0c1824c37b7c7"]]},{"id":"c3c4f09e3e5a8f62","type":"inject","z":"e78eac1c.8b9cf","name":"","props":[{"p":"payload"},{"p":"topic","vt":"str"}],"repeat":"","crontab":"","once":false,"onceDelay":0.1,"topic":".chess-board .h1","payload":"♛","payloadType":"str","x":1330,"y":340,"wires":[["dac0c1824c37b7c7"]]},{"id":"7f4acdca20a3afeb","type":"inject","z":"e78eac1c.8b9cf","name":"","props":[{"p":"payload"},{"p":"topic","vt":"str"}],"repeat":"","crontab":"","once":false,"onceDelay":0.1,"topic":".chess-board .h3","payload":"♝","payloadType":"str","x":1330,"y":420,"wires":[["dac0c1824c37b7c7"]]},{"id":"e363989376c50302","type":"inject","z":"e78eac1c.8b9cf","name":"","props":[{"p":"payload"},{"p":"topic","vt":"str"}],"repeat":"","crontab":"","once":false,"onceDelay":0.1,"topic":".chess-board tr.b td","payload":"♙","payloadType":"str","x":1320,"y":260,"wires":[["dac0c1824c37b7c7"]]},{"id":"236329b893a0e0d9","type":"inject","z":"e78eac1c.8b9cf","name":"","props":[{"p":"payload"},{"p":"topic","vt":"str"}],"repeat":"","crontab":"","once":false,"onceDelay":0.1,"topic":".chess-board tr.g td","payload":"♟","payloadType":"str","x":1320,"y":460,"wires":[["dac0c1824c37b7c7"]]},{"id":"dce9e7a2.d20c78","type":"ui_group","name":"Object detection","tab":"5132060d.4cde48","order":1,"disp":true,"width":"9","collapse":false},{"id":"5132060d.4cde48","type":"ui_tab","name":"Home","icon":"dashboard","disabled":false,"hidden":false}]

```

**Info...**

In this ↑ demo, I dont use images - i use chess characters copied from [here](http://www.i2symbol.com/symbols/chess) & set the `.text()` to `msg.payload`

I use CSS selectors to address the grid items e.g...

- a CSS selector of `.chess-board .a1` in `msg.topic` will set the `text()` of the 1st cell to the value in `msg.payload`
- a CSS selector of `.chess-board .b` in `msg.topic` will set the `text()` of all cells in row 2 to the value in `msg.payload`
- a CSS selector of `.chess-board td` in `msg.topic` will set the `text()` of all cells the value in `msg.payload`

---

<div class="post-metadata">

**Author:** ![Gunner](https://sea2.discourse-cdn.com/flex026/user_avatar/discourse.nodered.org/gunner/32/43582_2.png) [@Gunner](https://discourse.nodered.org/u/Gunner)\
**Post date:** [4 July 2021 23:41 UTC](https://discourse.nodered.org/t/node-red-ui-image-grid/47803/6 "2021-07-04T23:41:06Z")

</div>

> [@Steve-Mcl](#):
>
> In this ↑ demo, I dont use images - i use chess characters copied from [here](http://www.i2symbol.com/symbols/chess) & set the `.text()` to `msg.payload`

Not specifically topic related, but in Dark mode the text is white. I am too new to CSS to quite figure out how to change the colour of the placed text (not wanting to change everything)... if possible. I looked through the code, but only see how to change the backgrounds.

![image](https://us1.discourse-cdn.com/flex026/uploads/nodered/original/3X/8/e/8e0cbb8ec080433c7fece9ee3b4d0dd101ce5849.png)

---

<div class="post-metadata">

**Author:** ![Gunner](https://sea2.discourse-cdn.com/flex026/user_avatar/discourse.nodered.org/gunner/32/43582_2.png) [@Gunner](https://discourse.nodered.org/u/Gunner)\
**Post date:** [5 July 2021 04:50 UTC](https://discourse.nodered.org/t/node-red-ui-image-grid/47803/7 "2021-07-05T04:50:09Z")

</div>

Figured it out... went down the ui.control node path with no results until I realized... Since it changed due to Dark mode, then perhaps 🤔... yep... Theme had a custom option with text colours 🕶 And I learned more about ui.control (albeit using a change node and not the ui.control node... go fig).

UPDATE: And while that worked, perhaps it was not the best way after all. CSS in the Template node to the rescue 😁

![image](https://us1.discourse-cdn.com/flex026/uploads/nodered/original/3X/4/a/4a4c169d5c007c7ba4f8678ce231f3b5b0766d80.png)

```auto
<style>
.nr-dashboard-theme ui-card-panel {
    color: #606060;
}
</style>

```

---

<div class="post-metadata">

**Author:** ![qudek77](https://sea2.discourse-cdn.com/flex026/user_avatar/discourse.nodered.org/qudek77/32/44060_2.png) [@qudek77](https://discourse.nodered.org/u/qudek77)\
**Post date:** [7 July 2021 08:41 UTC](https://discourse.nodered.org/t/node-red-ui-image-grid/47803/8 "2021-07-07T08:41:42Z")

</div>

Wow! Thanks a lot. This is very very helpful. 😃 😃 😃

---

<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:** [21 July 2021 08:42 UTC](https://discourse.nodered.org/t/node-red-ui-image-grid/47803/9 "2021-07-21T08:42:23Z")

</div>

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