Global.get changes structure of the context

Hi, I have issue where global.get seems to 'regroup' elements of the object.
Here is context value copied out from context panel:

{"group":{"hide":["Tablet_Heat","Tablet_Weather","Tablet_Collector","Tablet_EV","Tablet_Electricity","Tablet_ElectricityP","Tablet_House","Tablet_Pump","Tablet_Carport","Tablet_Workshop","Tablet_Sauna","Tablet_Misc"],"show":["Tablet_Menu"]}}

Here is the object that I get after:
var myArr = global.get("Menu");
msg.payload = myArr;

{"group":{"hide":[],"show":["Tablet_Menu","Tablet_Heat","Tablet_Heat","Tablet_Weather","Tablet_Collector","Tablet_Heat","Tablet_House","Tablet_Heat","Tablet_Weather","Tablet_Collector","Tablet_House","Tablet_Carport","Tablet_Carport","Tablet_Carport"]}}

My code works fine on JS simulator with the original context. What I am missing here? Thanks. :slight_smile:

var Show = 'Tablet_Carport';
var myArr = global.get("Menu");

myArr.group.show.push(Show);
var index = myArr.group.hide.indexOf(Show);
myArr.group.hide.splice(index, 1);

msg.payload = myArr;
return msg

Although from what you have written here, i cannot see it but this is almost always due to objects/arrays being stored by reference.

e.g. If you store an object/array in global of flow context, then you edit the object/array later on, you will affect the stored value (because you only stored a pointer/reference to the original)

If you did not want that to happen, be sure to store a clone. You can use the deep copy option on a change node OR in a function you can use RED.util.cloneMessage(xxx)

e.g.

const menuClone = RED.util.cloneMessage(myArr)
global.set('Menu', menuClone)
1 Like

Thanks a lot! Yes, I did it as You suggested and now it seems to work as intended. I had no idea that if I am not using global.set I am still modifying the context. Does it apply to flow and node contexts too? I am using node and flow contexts a lot but did not noticed that behavior before.

Here in my code I do not need to global.set as I am just grabbing the object, modify and pass it over to ui control node. My code now is:

var Show = 'Tablet_Carport';
const myArr = RED.util.cloneMessage(global.get('Menu'));

myArr.group.show.push(Show);
var index = myArr.group.hide.indexOf(Show);
myArr.group.hide.splice(index, 1);

msg.payload = myArr;
return msg

Yes, if it is an object (Arrays are objects)

For the node & flow contexts the same RED.util.cloneMessage applies?

Yes. Context is context (regardless of scope). If you store an object, it is a reference & can be modified without calling .set

1 Like

Great, today I learned something new that will shorten my codes. :slight_smile: Thanks again!

That command is not directly related to context. It will clone any object.

1 Like