Bridging Weweb and Javascript Variables in under 15 minutes

In this tutorial Ray Deck walks through how to connect external JavaScript code to WeWeb’s state management system. He starts by creating a text variable (headerInfo) in WeWeb, binding it to a heading, and adding a button workflow that updates the variable when clicked. He then attempts to manipulate the variable from a custom script tag, encountering errors because the variable isn’t a global JavaScript variable. By enabling the “Show Dev Information” panel, he copies the internal variable ID and discovers the global `dublib` object that WeWeb injects. Using `dublib.variable.getValue` and `dublib.variable.updateValue` with the copied ID, he demonstrates reading and writing the WeWeb variable from any JavaScript context. He builds a timer with `setInterval` that calculates elapsed time, formats minutes, seconds, and milliseconds, and pushes the formatted string back into the WeWeb variable each second, causing the bound heading to update in real time. Throughout, he shows debugging steps in DevTools, explains common pitfalls (e.g., typos, missing IDs), and encourages viewers to explore deeper integrations via StateChange.ai’s community and office hours.
Chapters
So WeWeb makes it very easy for you to update code and the state of things inside WeWeb, but how can we bridge external JavaScript to be able to work inside WeWeb itself? So if I were to say I want to have, I'll just take an example here. Let's say I have a heading. I'm gonna drag over heading here, and the heading is going to say, we want to just say hello, right? Hello. And then it'll just say hello. But it can be more interesting, right, to bind it to a variable. So I can go over to data. I can say, let's add a variable and the variable is going to be called header info. And we will call it and we'll give it to the, make it type of text and we'll take it. I have no info yet. And we will create this. Super. So now if I were to go over to your, go over to the header and I were to say, let's click not sanitize. Let's click into the formula for the text instead of saying, hello. Hello, I could say, instead of saying hello, I could instead have it use the Vario, right? Like the header info that I have here, and then clean that up. And then all of a sudden it just shows the actual header info. Fantastic. Now it's, we, web makes it very easy for me to do something like let's add a button click. And if I were to click it, I could have an action on that button. Let's add a workflow to it. And on that action, I'm going to set a variable value, right? I'm going to change variable value. And the variable I'm going to change is header info. And I'm going to change the header info to "You clicked me." And then we'll say that's fine and we'll close it. That way, if I were to go and preview it, I could click this and it says, "You clicked me." Now that's all fine inside of WeWeb, but what if we want to have a little bit of JavaScript, which is going to maybe operate on a counter or something? Let's talk about that in the context of script tag. Let's create a new script file. And we will say, let's say we want to just have a setTimeout. And we're going to have inside that timeout— I don't need the dash there. Do. Cool. And we would want to say, we'll say const myCounter equals 0. Actually, it'll be a let. And we'll say every time this counter ticks, which is going to be comma 1000, we're going to say— in fact, let's do better. startTime equals date. Date.now. And we want to basically say that current, const currentTime equals Date.now minus startTime. And then what we want to do is update a variable with whatever currentTime is, right? And we'll say const current equals currentTime divided by 1000. Right, that way I have a current number of seconds. And then I want to basically set header info equals current. Now this isn't going to work, right? Because header info isn't actually a global variable, but let's just grab this for a second and talk about how we can make use of it. So we're going to copy the script tag, actually as a WeWeb snippet, because we're dealing with WeWeb right now. And we go over to JavaScript test and we will go to our page using the usual script tag formula. We're going to go to, we're going to trigger a workflow, add a workflow. To the page load, add an action, and it's going to be custom JavaScript action. Edit the code. Now we're just gonna copy over what we got from script tag to make that work. So now we have a script tag that is now embedded, uh, into our code and we'll save that and we'll say close and all of that. And now, uh, we're going to just refresh the page and we're gonna find that the, uh, the I have no info yet is just sitting there. And in the meantime, if we were to open this guy up, it's just announced that it has errors coming over and over. Cause it says startTime is not a function, which actually is, that's a different kind of problem. Equal, oh, startTime. Yep. It's not a function. And we'll save that and we'll say, okay, now it's saved on the server. We're going to refresh this. And now we don't have that same error. But we will probably get is instead the error of. That there's no such variable that is called, no such variable that is called currentSex at that point. So we're gonna say, we'll just do a console.log, working over here. And we will say, all right, that's saved on server. That's fine. And now we're gonna go back over here. We're gonna see if working over here shows up just to show that the script tag is actually firing off. It says working over here. It fires once and only once. Of course, that's because it's set to a setTimeout. Let's do a setInterval. And that way it'll always fire as long as we want it to. We go back over here, we do a refresh. And you'll notice that the— it says I am working after this, the WeWeb page loads up. It'll say I'm working over here, and now it's just continuously going, but it doesn't do anything else. And the reason it's not doing anything else is because it's looking for something called header info that does not yet exist. And we're going, and the, and that's the reason why it's not updating header info, even though we all defined header info here as a variable. So how do we find that variable? And here we can, then this is where WeWeb's little icon up here really helps. This little developer-ish icon, not moving to the developer editor, that's a different one that's used for doing view components or what have you. But there's something down here. It says Advanced, Hide or Show Dev Information. You want it to probably saying Show Dev Information for you right now. And as a result, if you were to go take a look at your elements like this, there was an additional button you might have noticed before that's not currently present. But if we click on this and we say Show Dev Information and we go to here, you'll see, hey, it looks, says Copy ID. And Copy ID is gonna be really important. Because yeah, that's the actual ID of the variable. Now let's talk about how we can play with this for a little bit. The, and we can have ourselves just a little bit of fun. Let's go back to the page where it says I have no info yet. And let's talk about how we were able to update that variable from outside the WeWeb context. And the, near as I can tell, the developer documentations don't have documentation of what we're about to do here. But it's all sort of stuff I was getting from the, from the dev tools over here. So there's a global variable that like WeWeb attaches. Called, uh, dub dub lib. And dub dub lib has a whole bunch of methods to it, a whole bunch of members, a lot of which are prefixed with dub. That can be pretty handy to work with. And one of them is called— let me scroll down here— dub dub variable. And dub dub variable allows you both get variables and update variables. And in order for you to get or update the variable, we're going to need to pass in the ID of that variable. And that's the reason why that copy that we just did is so important. So we can do dublib just right here in DevTools,.dubdub variable,.getValue. And then the value we need to pass is header info. No, this is not going to work because it's gonna say can't find header info. But what it can do is find— nope, that was not right. What it can do is find, I go to data. Click on copy ID here and it says copy to clipboard and we can paste this in. Oh, hey, look, we gotta put in quotation marks. So we'll put in quotation marks because that's something that code requires us to do. And we do this and it says, I have no info yet. Hey, it looks very much like the thing that we have over here in the title, cuz that's the thing we put in. So in addition to being able to, so that this allows us to get this information from any context. So this did not have to be from inside WeWeb. This could be from any arbitrary JavaScript you use by doing www.lib.variable.getvalue. As long as we know what the variable ID is, and the variable ID again, we get by doing the advanced dev information. The, the next thing we can do is we can say, let's edit the variable value. lib.variable.update_variable, update value. In order for us to update the value, we're going to need to provide it two arguments. The first argument is going to be the ID of the variable in question. And the second is going to be what we want to set it to. And then that will immediately change things in any view that you have. And so that updates the variable and it updates any element that's bound to that variable because it's all part of the state management system. So it actually integrates very nicely into the rest of what WeWeb does. These two things, getValue and updateValue, allow you to teleport information from an arbitrary JavaScript to, uh, WeWeb itself. So let's talk about how we might do that by, through the timer that we had set up here. Now we know what the value, what this value is. Let's just copy this guy for a second, and we're going to go back over to our script tag, and we're going to say, okay, all this is very nice, and instead of saying header info equals current sec, we're going to say, we're going to say, we're going to have const newLabel equals timeElapsed is— and we'll say const equals currentMath, and we'll say const ms equals the sex— what am I going to do here— minus sex.timeElapsed. .4. And we'll then also say const minutes equals sex.64 divided by— right, this is a classic way of dividing things into minutes. const seconds equals math. Basically, it's going to be.4 minus— so this is all just a little bit of technique to go build out to create some separation for, for minutes, seconds, and milliseconds. And so we'll say is equal to plus minutes plus, plus seconds plus ms, right? So now we can get 0 seconds milliseconds, and it's not going to like prepend the stuff correctly, but, but who cares? The point is we're creating this new variable, and then we're going to say instead of what we want to send it to, we're going to set the variable to this, this timer that's just running on the page. And this should have the effect— copy, or just prettify that thing— and this should have the effect of basically every second updating the value to this new time elapsed based on how the timer is, based on how the timer is running. So now we've prettified it, it's already in the script tag, which means all we need to do is refresh the page. And it'll need to reload the loader to see how all this stuff works. And then we're gonna wait for this to go. It'll probably error for the first few seconds as it says there's nothing for it to update just yet. It says current text is not defined. And why is that not defined? It says current text equals current time. Oh, because I have a typo in here. There we go. And we'll say, prettify that. And we'll go back over to here. Whenever creating code, gotta worry about typos. And of course it looks terrible, but the, uh, but it starts to tell a story, right? Of I've got my seconds, which are just iterating upward. And of course we can start to do things like saying we only want the very top of our milliseconds or what have you. Maybe the milliseconds we don't think are nearly as exciting to show here. Maybe you want to show it every 500 milliseconds or what have you. But this just shows you how you can focus on just this little thing here, which is this timer, right? That we're doing on the outside, or it could be like related to Capture or some other feature that you're trying to bring into your WeWeb environment. And you don't need to be owning all the concerns, right? By doing it, trying to force it into the, the, the no-code context, because you can build this bridge. And the way that we're building this bridge is through using this dublib and the member of it called dub dub variable and making use of update value. And then of course we can also say let's const relayValue equals dublib.variable.getValue, and then you just pass it that same key. And then we can just do a console.log relayValue. I just say value, we web is the relay value, uh, and we copy that. And now this sort of allows to show how we can get both in and out where we're going to do update variable, we're going to then do the get variable. Let's test that out. Wait for the whole thing to load. And it says the value in WeWeb is whatever it was. So now we can see how we can, from the context of our JavaScript, get code out of WeWeb, and how we can, from the context of our WeWeb, get code out of our JavaScript without having to do any super crazy fancy bridges. It's just one line of code and being able to get this stuff from inside your script tag. And if you want to learn more about script tag and how we do hard things that are at the corner of no-code low-code to get more superpowers out of our no-code tools, I would encourage you to check out what we're doing over at StateChange.ai, where we have a combination of daily office hours. We do, we have a community where we talk about these things as well as providing tools, try to make it easier for us to do the hardest 5% of our no-code, low-code projects. Hope to see you there soon.










