Global variable in uibuilder

I am using the uibuilder tool which is very useful.

inside the .js file, I initialize a variable in the data object.

var app1 = new Vue({
el: '#app',
data: {
startMsg : 'Vue has started, waiting for messages',
feVersion : '',
counterBtn : 0,
inputChkBox : false,
socketConnectedState : false,
serverTimeOffset : '[unknown]',
imgProps : { width: 75, height: 75 },

    msgRecvd    : '[Nothing]',
    msgsReceived: 0,
    msgCtrl     : '[Nothing]',
    msgsControl : 0,

    msgSent     : '[Nothing]',
    msgsSent    : 0,
    msgCtrlSent : '[Nothing]',
    msgsCtrlSent: 0,
    startAstrand: false
}, // --- End of data --- //

Then I'd like to use this varaible everywhere in my code, but it looks like it's not possible.

When I print his value inside a function inside methods it works. Then on the mounted function, I have

uibuilder.onChange('msg', function(newVal){
console.log(this.startAstrand)
}

I got undefined. Does someone know why ?

Thanks

This will be due to this scope & not really a node-red or uibuilder question (more of a vue question) but we are helpful folk here.

So in the mounted function, there will be something like var that = this or var myApp = this or var myvue = this (I forget what it is) but - find it then instead of using this use that.

e.g.

uibuilder.onChange('msg', function(newVal){
console.log(that.startAstrand)
}

PS - please use the </> button not the " button for posting code :slight_smile:

or just put code between three back ticks
```
paste code here to make it beautiful and unfettered by the forum
```

2 Likes

To further explain it, this is a JavaScript thing, and since Vue and most things that you'd use on Uibuilder have javascript inside, it's definitely relevant. You might also run into this if you're doing complex stuff in function nodes, so it is relevant for the forums in more reason than one :slight_smile:

In JavaScript, this points to the scope of the current function you're in. Say that you have a structure that looks like this (pseudocode for showing):

// code before A
function A(...) {
   // inside A
}
// code after A

Anything you define to this inside A, is only available within that function.
However, it gets complicated when you have functions within functions, like in the mounted function of a Vue app in Uibuilder:

// before function (position 1)
mounted: function (...) {
    // inside function mounted (position 2)
    uibuilder.onChange('msg', function(newValue) {
        // in onChange function (position 3)
    }
    // inside function mounted (position 4)
}
// after function mounted (position 5)

When you're at position 2, this.startAstrand refers to the variable startAstrand that you put in your data structure. On posiition 3 however, this has changed to become local in the onChange function, and holds no longer a reference to the data structure. You can get around that by defining a variable for yourself inside the outer function mounted, with a name that sounds logical for you, for example that or vueApp (which I think is what Julian defaults to in the examples), and assign it the value of this, because at position 2 this still points to the right values. As the variable defined in position 2 will have a wide enough scope to be reachable at positions 3 and even 4, you can then use your that.startAstrand or vueApp.startAstrand or whatever you created in position 3. In position 4 you can choose whether you'd like to use this.startAstrand again, or go with the earlier created that.startAstrand or similar.

It's a bit abstract, but I hope that helps.

2 Likes

Thank you to both of you, those explanations were very useful, I learnt something and it works perfectly !!

Just to note that the template .js file already has this assigned to a variable - vueApp inside the mounted function for that very reason.

In fact though, you don't really need to do that since I already assign the new vue instance to app1 right at the start. So both app1 and vueApp are pretty much the same thing.

But certainly, the bottom line in JS (and probably in all languages that implement this) is that if you have sub-functions/methods defined inside another function or class, it is always safer to take a reference to this.

Because JavaScript mostly assigns "references" rather than "copies" when you assign one thing to another, you don't generally have to worry about assignments making your code bloated. (strictly speaking, JS does a copy if the thing on the right hand side of the equals sign is a "primitive" data type such as a number, string, boolean, etc. For everything else, I believe it just creates a reference - a "link" if you like.)

1 Like

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