# Handling partial msg.payload items in a 2.0 Template node

**URL:** <https://discourse.nodered.org/t/handling-partial-msg-payload-items-in-a-2-0-template-node/98205>\
**Category:** Dashboard\
**Tags:** dashboard-2\
**Created:** [18 July 2025 19:27 UTC](https://discourse.nodered.org/t/handling-partial-msg-payload-items-in-a-2-0-template-node/98205 "2025-07-18T19:27:35Z")\
**Posts on this page:** 11\
**Page:** 1

<div class="post-metadata">

**Author:** ![KSum](https://sea2.discourse-cdn.com/flex026/user_avatar/discourse.nodered.org/ksum/32/78579_2.png) [@KSum](https://discourse.nodered.org/u/KSum)\
**Post date:** [18 July 2025 19:27 UTC](https://discourse.nodered.org/t/handling-partial-msg-payload-items-in-a-2-0-template-node/98205/1 "2025-07-18T19:27:35Z")

</div>

I have an instance where msg.payload will not have all the keys defined for items which I want to show in a Dashboard 2.0 Template node. In the example below (greatly simplified from my needs) I will receive a message where msg.payload.x may be defined OR msg.payload.y may be defined, but not both together. This gets more complicated in that I will eventually have (still simplified):

- msg.payload.zone1.x
- msg.payload.zone1.y
- msg.payload.zone2.x
- msg.payload.zone2.y

and want to save them as different object:

- zone1.x
- zone1.y
- zone2.x
- zone2.y

My problem is that when I receive msg.payload.x it clears out any existing msg.payload.y. I am guessing the is a Vue way to handle this but cannot figure it out inside the node. Admittedly, I have never used Vue prior to recent attempts to do things with the Template node.

Below is the template for my basic example. What am I missing?

```auto
<template>
    <p>X = {{ msg.payload?.x }}</p>
    <p>Y = {{ msg.payload?.y }}</p>
    <p>X+Y = <div v-html="addValue"></div></p>
    <p>Sensor Angle = {{ msg.angle }}</p>
</template>

<script>
    export default {
        watch: {
            //Watch for any changes to msg and act on them.
            //This is run when the dashboard is loaded as well
            msg: function () {
                this.addValue = this.msg.payload.x + this.msg.payload.y;
            }
        },
    }
</script>

```

Here is a sample flow with inject nodes I have used to test with:

```auto
[{"id":"f3564535b8fc6abf","type":"inject","z":"01a9e096a69c7202","name":"","props":[{"p":"payload.x","v":"3","vt":"num"}],"repeat":"","crontab":"","once":false,"onceDelay":0.1,"topic":"","x":1590,"y":460,"wires":[["cef846095e925344"]]},{"id":"1cdd9cec45819237","type":"inject","z":"01a9e096a69c7202","name":"","props":[{"p":"payload.y","v":"6","vt":"num"}],"repeat":"","crontab":"","once":false,"onceDelay":0.1,"topic":"","x":1590,"y":500,"wires":[["cef846095e925344"]]},{"id":"b9441e0457637205","type":"inject","z":"01a9e096a69c7202","name":"","props":[{"p":"payload.x","v":"5","vt":"num"},{"p":"payload.y","v":"7","vt":"num"}],"repeat":"","crontab":"","once":false,"onceDelay":0.1,"topic":"","x":1590,"y":540,"wires":[["cef846095e925344"]]},{"id":"194cdce48b33540a","type":"inject","z":"01a9e096a69c7202","name":"","props":[{"p":"angle","v":"55","vt":"num"}],"repeat":"","crontab":"","once":false,"onceDelay":0.1,"topic":"","x":1590,"y":580,"wires":[["cef846095e925344"]]},{"id":"cef846095e925344","type":"ui-template","z":"01a9e096a69c7202","group":"0db8d9f5bdc794eb","page":"","ui":"","name":"Template test 3","order":3,"width":"12","height":"6","head":"","format":"<template>\n <p>X = {{ msg.payload?.x }}</p>\n <p>Y = {{ msg.payload?.y }}</p>\n <p>X+Y = <div v-html=\"addValue\"></div></p>\n <p>Sensor Angle = {{ msg.angle }}</p>\n</template>\n\n<script>\n export default {\n watch: {\n //Watch for any changes to msg and act on them.\n //This is run when the dashboard is loaded as well\n msg: function () {\n this.addValue = this.msg.payload?.x + this.msg.payload?.y;\n }\n },\n }\n</script>\n","storeOutMessages":true,"passthru":true,"resendOnRefresh":true,"templateScope":"local","className":"","x":1840,"y":500,"wires":[[]]},{"id":"0db8d9f5bdc794eb","type":"ui-group","name":"My Group","page":"92d2e5483adf6001","width":"12","height":"6","order":1,"showTitle":true,"className":"","visible":"true","disabled":"false","groupType":"default"},{"id":"92d2e5483adf6001","type":"ui-page","name":"Simulation","ui":"4c2bb00f7172c414","path":"/page7","icon":"home","layout":"grid","theme":"d8f055e104cc1454","breakpoints":[{"name":"Default","px":"0","cols":"3"},{"name":"Tablet","px":"576","cols":"6"},{"name":"Small Desktop","px":"768","cols":"9"},{"name":"Desktop","px":"1024","cols":"12"}],"order":2,"className":"","visible":true,"disabled":"false"},{"id":"4c2bb00f7172c414","type":"ui-base","name":"My 1st 2.0 Dashboard","path":"/dashboard","includeClientData":true,"acceptsClientConfig":["ui-notification","ui-control"],"showPathInSidebar":false,"headerContent":"page","navigationStyle":"default","titleBarStyle":"default","notificationDisplayTime":5},{"id":"d8f055e104cc1454","type":"ui-theme","name":"Default Theme","colors":{"surface":"#ffffff","primary":"#0094CE","bgPage":"#eeeeee","groupBg":"#ffffff","groupOutline":"#cccccc"},"sizes":{"pagePadding":"12px","groupGap":"12px","groupBorderRadius":"4px","widgetGap":"12px"}}]

```

---

<div class="post-metadata">

**Author:** ![omrid](https://avatars.discourse-cdn.com/v4/letter/o/77aa72/32.png) [@omrid](https://discourse.nodered.org/u/omrid)\
**Post date:** [18 July 2025 20:41 UTC](https://discourse.nodered.org/t/handling-partial-msg-payload-items-in-a-2-0-template-node/98205/2 "2025-07-18T20:41:57Z")

</div>

My personal preference is not to rely on behind-the-scenes parsing of moustach-ed variables (e.g. `{{ msg.payload }}` ) in the HTML (`<template>`) area, but rather handle the message in the javascript area, and have full visibility & control on how I handle incoming data.

I set a message listener in the `mounted()` area of the template. When I receive a message, I can inspect it (then filter, transform, enrich etc.) and set the relevant msg properties into the template's `data()` area, which is mapped to the visual HTML elements, and automatically updates them upon change.

---

<div class="post-metadata">

**Author:** ![Colin](https://sea2.discourse-cdn.com/flex026/user_avatar/discourse.nodered.org/colin/32/17040_2.png) [@Colin](https://discourse.nodered.org/u/Colin)\
**Post date:** [19 July 2025 08:11 UTC](https://discourse.nodered.org/t/handling-partial-msg-payload-items-in-a-2-0-template-node/98205/3 "2025-07-19T08:11:44Z")

</div>

The reason your existing code does not do what you want is that it is evaluated each time you get a new message. Data from previous messages is not retained. One easy way to make it work is to build a merged set of properties from all previous messages before passing it to the template. Add a Function node containing this code in front of the template

```auto
// fetch previous combined payload
let previousPayload = context.get("previous") ?? {}
// merge the new payload parts into the previous
// Edit, corrected the next line, I had the merge the wrong way round
msg.payload = {...previousPayload, ...msg.payload}
// save the merged payload
context.set("previous", msg.payload)
return msg

```

---

<div class="post-metadata">

**Author:** ![Colin](https://sea2.discourse-cdn.com/flex026/user_avatar/discourse.nodered.org/colin/32/17040_2.png) [@Colin](https://discourse.nodered.org/u/Colin)\
**Post date:** [19 July 2025 09:47 UTC](https://discourse.nodered.org/t/handling-partial-msg-payload-items-in-a-2-0-template-node/98205/4 "2025-07-19T09:47:13Z")

</div>

Oops, I had the merge the wrong way round, it should be  
`msg.payload = {...previousPayload, ...msg.payload}`

I will adjust the post above.

---

<div class="post-metadata">

**Author:** ![Colin](https://sea2.discourse-cdn.com/flex026/user_avatar/discourse.nodered.org/colin/32/17040_2.png) [@Colin](https://discourse.nodered.org/u/Colin)\
**Post date:** [19 July 2025 09:52 UTC](https://discourse.nodered.org/t/handling-partial-msg-payload-items-in-a-2-0-template-node/98205/5 "2025-07-19T09:52:49Z")

</div>

Alternatively (and better) you can do the same thing with a Join node configured like:

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

For either of these solutions to work you will also, of course, have to move any additional properties that you want (such as angle) into the payload.

---

<div class="post-metadata">

**Author:** ![KSum](https://sea2.discourse-cdn.com/flex026/user_avatar/discourse.nodered.org/ksum/32/78579_2.png) [@KSum](https://discourse.nodered.org/u/KSum)\
**Post date:** [19 July 2025 12:08 UTC](https://discourse.nodered.org/t/handling-partial-msg-payload-items-in-a-2-0-template-node/98205/6 "2025-07-19T12:08:36Z")

</div>

My ultimate goal is to display a plotly graph and dynamically change a couple items as their value changes. I believe merging all the data will cause the entire graph to redraw but I do know that I can provide a modified variable and have just that one item redeaw. My current "solution" is to set data outside of msg.payload and use values such as msg.angle. I was hoping there is a way with vue to assign data from msg.payload.\_\_\_ to a variable inside the template and ignore any that have not changed.

---

<div class="post-metadata">

**Author:** ![KSum](https://sea2.discourse-cdn.com/flex026/user_avatar/discourse.nodered.org/ksum/32/78579_2.png) [@KSum](https://discourse.nodered.org/u/KSum)\
**Post date:** [19 July 2025 12:19 UTC](https://discourse.nodered.org/t/handling-partial-msg-payload-items-in-a-2-0-template-node/98205/7 "2025-07-19T12:19:29Z")

</div>

Using this method, is there a way to check that the key exists and only define/change variables for items passed? I have tried using  
`msg.payloasd.myKey !== undefined`  
and had no luck. Maybe in using it in the wrong areas? I had it under the watch section, inside a function which draws/modifies the graph. I did not use it in a data() section. I also have since fine reference to a computed() section but have not figured out how I might use it.

---

<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:** [19 July 2025 12:38 UTC](https://discourse.nodered.org/t/handling-partial-msg-payload-items-in-a-2-0-template-node/98205/8 "2025-07-19T12:38:24Z")

</div>

> [@KSum](#):
>
> I was hoping there is a way with vue to assign data from msg.payload.\_\_\_ to a variable inside the template and ignore any that have not changed.

You can condition the setting of local data variables using any property of the message you desire.

e.g.

```html
<template>
    <div>
        <p>Current x: {{ x }}</p>
        <p>Current y: {{ y }}</p>
        <p>Current sum: {{ sum }}</p>
        <v-btn @click="send({payload:sum})">Send sum</v-btn>
    </div>
</template>

<script>
    export default {
        data() {
            return {
                x: 0,
                y: 0
            }
        },
        watch: {
            msg: function () {
                if (this.msg.topic === "update-x") {
                    this.x = msg.payload
                } else if (this.msg.topic === "update-y") {
                    this.y = msg.payload
                } if (this.msg.topic === "update-xy") {
                    this.x = msg.payload.x
                    this.y = msg.payload.y
                }
            }
        },
        computed: {
            sum: function () {
                return this.x + this.y
            }
        }
    }
</script>

```

---

<div class="post-metadata">

**Author:** ![omrid](https://avatars.discourse-cdn.com/v4/letter/o/77aa72/32.png) [@omrid](https://discourse.nodered.org/u/omrid)\
**Post date:** [19 July 2025 13:19 UTC](https://discourse.nodered.org/t/handling-partial-msg-payload-items-in-a-2-0-template-node/98205/9 "2025-07-19T13:19:09Z")

</div>

> [@KSum](#):
>
> Using this method, is there a way to check that the key exists and only define/change variables for items passed? I have tried using  
> `msg.payloasd.myKey !== undefined`  
> and had no luck. Maybe in using it in the wrong areas? I had it under the watch section, inside a function which draws/modifies the graph. I did not use it in a data() section. I also have since fine reference to a computed() section but have not figured out how I might use it.

I assume they typo `msg.payloasd` is just here in the post and not in your code.

There are many ways you can do this:  
Colin's approach is perfectly good, yet requires additional pre-processing before the message comes into the node.  
`compute()/watch()` ? I assume it works per the example in the documentation, but have never tried it.  
If it was up to me (again, personal preference only), I would go to the `<script>` area and do something such as

```auto
export default {
  data () {
    return {
      x: null,
      y: null
    }
  },
  mounted() {
    const vThis = this; // save current 'this', for use inside callbacks & internal scopes

  // Set message listener
  this.$socket.on('msg-input:' + this.id, function(msg) {
    if (msg?.payload.x !== undefined)
      vThis.x = msg.payload.x;
    if (msg?.payload.y !== undefined)
      vThis.y = msg.payload.y;
    processXY(vThis.x,vThis.y);
  });
}

```

---

<div class="post-metadata">

**Author:** ![KSum](https://sea2.discourse-cdn.com/flex026/user_avatar/discourse.nodered.org/ksum/32/78579_2.png) [@KSum](https://discourse.nodered.org/u/KSum)\
**Post date:** [19 July 2025 16:33 UTC](https://discourse.nodered.org/t/handling-partial-msg-payload-items-in-a-2-0-template-node/98205/10 "2025-07-19T16:33:48Z")

</div>

Thank you all for the information. I am going to use a combination of the information from both @Steve-Mcl and @omrid. I revisited the use of `msg.payload.myKey !== undefined` (yes, there was a typo as I was responding via my phone) and think I will use that under the watch section. While the use of topic would currently make things easier my messages are currently coming from MQTT) I do not think that will be the case for me long term as I intend to ultimately receive messages from a different source. I am going to keep it as a possibility, but I found that unless every message received had a topic the previous topic was apparently retained and used in the conditional checking.

What I have below is working for my testing as long as all messages have a topic with some not passing the test.

```auto
<template>
    <p>X = {{ myx }}</p>
    <p>Y = {{ myy }}</p>
    <p>X+Y = <div v-html="addValue"></div></p>
    <p>Sensor Angle = {{ msg.angle }}</p>
</template>

<script>
    export default {
        data() {
            return {
                myx: 0,
                myy: 0
            }
        },
        watch: {
            //Watch for any changes to msg and act on them.
            //This is run when the dashboard is loaded as well
            msg: function () {
                if (this.msg.topic === "myx") {
                    this.myx = this.msg.payload.x + 10;
                } else if (this.msg.payload.x !== undefined){
                    this.myx = this.msg.payload.x;
                }

                if (this.msg.payload.y !== undefined){
                    this.myy = this.msg.payload.y;
                }              
                this.addValue = this.myx + this.myy;
            }
        },
    }
</script>

```

---

<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:** [18 August 2025 16:33 UTC](https://discourse.nodered.org/t/handling-partial-msg-payload-items-in-a-2-0-template-node/98205/11 "2025-08-18T16:33:58Z")

</div>

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