Problem add Object to Array

Hi together,

I'm stuck with a beginner Problem to push an Object to an Array of Object...

What I want to do:
I have a dashboard where the user can put in different values which are stored in several object-properties. With every input the whole object is stored in global context variable "tempstore".
When all inputs are done, I want to push the object to an array of object.
What happens is, that when I add a new Object to my array, all Object-properties of former array elements get the property-values of the last added array element...what am I doing wrong??

JS-Code to set a property from dashboard. Have it for 3 properties (val1, val2, val3):

var local = global.get ("tempstore") || {};
local.val1 = msg.payload;
global.set ("tempstore", local);
return msg;

Code to save the object to array:

var local_arr = global.get ("array") || [];
var local_tempstore = global.get ("tempstore") || {};

local_arr[local_arr.length] = local_tempstore;
global.set("array",local_arr);

return msg;

when the first Object was
val1: "value1", val2: 1, val3: 44100000
and the second Object was
val1: "value2", val2: 2, val3: 44100000
the result is...
image

I hope somebody can help me with this problem - thanks!

Use

local_arr.push(local_arr)

The code you have should work I think, though push is obviously cleaner. I suspect you may be falling over the fact that objects in javascript are accessed by reference, so it may be that when you setup the two messages that feed into the first function that you are actually passing the same object in the payload. How are you generating those two messages?
If you don't think that is the problem then can you construct a mini-flow showing the problem and export that here?

Thanks for your replies. I think you are right Colin...I am not really used to call by reference...I did a check with RED.util.cloneMessage...but to be honest...I don't understand why it works now and did not before...

First question:
In some other posts when reading into storing data in context I thought to have understood to first get my element from global storage by storing it in a local variable... var local_val = global.get("value")...
Then I thought I have to manipulate the local variable and store it back to context by calling global.set("value", local_var). But why should I use global.set to store the local value back to context, when manipulating my local_var already manipulates context because of the command local_val = global.get("value")....?

Second question
I changed my code als follows and now it works:

Get elements from dashboard and safe it temporarily in context:

var local = global.get ("tempstore") || {};
local.val1 = msg.payload;
//global.set ("tempstore", local);  -> Does not matter, if I use this line or not. 
return msg;

Safe temporary variable with the three elements in an array of object in context when clicking on button:

var local_arr = RED.util.cloneMessage(global.get ("array")) || [];
var local_tempstore = RED.util.cloneMessage(global.get ("tempstore")) || {};

local_arr[local_arr.length] = local_tempstore;
global.set("array",local_arr);

return msg;

So when using cloneMessage it works....but why not without it. I thought the line local_arr[local_arr.length] = local_tempstore; means that the new array element now points to the adress of local_tempstore....why should this line also alter older array elements?

Last question:
Is there a more elegant way than I did it to collect data from multiple inputs from dashboard and then store it to context by clicking a button?

Here is my example flow:

[{"id":"59d61ca8.536c24","type":"tab","label":"arraytest","disabled":false,"info":""},{"id":"37232382.b39d0c","type":"ui_button","z":"59d61ca8.536c24","name":"New array element","group":"6aeb6a04.8ceb74","order":0,"width":0,"height":0,"passthru":false,"label":"New array element","tooltip":"","color":"","bgcolor":"","icon":"","payload":"","payloadType":"str","topic":"","x":170,"y":380,"wires":[["97d2b91a.c48f88"]]},{"id":"b5fe945c.94b5c8","type":"inject","z":"59d61ca8.536c24","name":"Init","topic":"","payload":"","payloadType":"date","repeat":"","crontab":"","once":false,"onceDelay":0.1,"x":130,"y":160,"wires":[["7062d938.8c66f8"]]},{"id":"7062d938.8c66f8","type":"function","z":"59d61ca8.536c24","name":"declare vars","func":"var array = [];\nvar tempstore = {val1 : \"\", val2 : \"\", val3 : \"\"};\n\nglobal.set (\"array\", array);\nglobal.set(\"tempstore\", tempstore);\n\n\nreturn msg;","outputs":1,"noerr":0,"x":380,"y":160,"wires":[[]]},{"id":"e2b13d93.e78ea","type":"ui_text_input","z":"59d61ca8.536c24","name":"Value 1","label":"Value 1","tooltip":"","group":"6aeb6a04.8ceb74","order":1,"width":0,"height":0,"passthru":true,"mode":"text","delay":300,"topic":"","x":140,"y":220,"wires":[["f451c7e7.bd8018"]]},{"id":"9bd4073c.45bc38","type":"ui_text_input","z":"59d61ca8.536c24","name":"Value 2","label":"Value 2","tooltip":"","group":"6aeb6a04.8ceb74","order":1,"width":0,"height":0,"passthru":true,"mode":"number","delay":300,"topic":"","x":140,"y":260,"wires":[["7aebbb92.5108c4"]]},{"id":"b5212d75.dbe24","type":"ui_text_input","z":"59d61ca8.536c24","name":"Value 3","label":"Value 3","tooltip":"","group":"6aeb6a04.8ceb74","order":1,"width":0,"height":0,"passthru":true,"mode":"time","delay":300,"topic":"","x":140,"y":300,"wires":[["5cdd891b.6c8828"]]},{"id":"60c671bd.773c8","type":"ui_button","z":"59d61ca8.536c24","name":"Delete array Element","group":"6aeb6a04.8ceb74","order":0,"width":0,"height":0,"passthru":false,"label":"Delete array Element","tooltip":"","color":"","bgcolor":"","icon":"","payload":"","payloadType":"str","topic":"","x":180,"y":420,"wires":[["a118a1ce.aee24"]]},{"id":"f451c7e7.bd8018","type":"function","z":"59d61ca8.536c24","name":"store value","func":"var local = global.get (\"tempstore\") || {};\nlocal.val1 = msg.payload;\n//global.set (\"tempstore\", local);\nreturn msg;","outputs":1,"noerr":0,"x":330,"y":220,"wires":[[]]},{"id":"97d2b91a.c48f88","type":"function","z":"59d61ca8.536c24","name":"new array element","func":"var local_arr = RED.util.cloneMessage(global.get (\"array\")) || [];\nvar local_tempstore = RED.util.cloneMessage(global.get (\"tempstore\")) || {};\n\nlocal_arr[local_arr.length] = local_tempstore;\nglobal.set(\"array\",local_arr);\n\nreturn msg;","outputs":1,"noerr":0,"x":470,"y":380,"wires":[[]]},{"id":"a118a1ce.aee24","type":"function","z":"59d61ca8.536c24","name":"delete array element","func":"var local = global.get (\"array\") || [];\nif (local.length > 0)\n{\n    local.splice(0, 1); \n}\n\nreturn msg;","outputs":1,"noerr":0,"x":480,"y":420,"wires":[[]]},{"id":"7aebbb92.5108c4","type":"function","z":"59d61ca8.536c24","name":"store value","func":"var local = global.get (\"tempstore\") || {};\nlocal.val2 = msg.payload;\n//global.set (\"tempstore\", local);\nreturn msg;","outputs":1,"noerr":0,"x":330,"y":260,"wires":[[]]},{"id":"5cdd891b.6c8828","type":"function","z":"59d61ca8.536c24","name":"store value","func":"var local = global.get (\"tempstore\") || {};\nlocal.val3 = msg.payload;\n//global.set (\"tempstore\", local);\nreturn msg;","outputs":1,"noerr":0,"x":330,"y":300,"wires":[[]]},{"id":"6aeb6a04.8ceb74","type":"ui_group","z":"","name":"arraytest1","tab":"65f4b3d5.cbcf4c","disp":false,"width":"6","collapse":false},{"id":"65f4b3d5.cbcf4c","type":"ui_tab","z":"","name":"arraytest","icon":"dashboard","disabled":false,"hidden":false}]

Thank you!

enter three back tics, then on a new line your code, then three more back tics on another new line. I edited your post so you can see how to do it

Ok, I got it, sometimes it needs some sleep in between. Every array element points to local_tempstore and with that to the same adress in global context...

Thanks for your Help!

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