One important thing to understand when scripting with the component event handlers is how to access properties from other components residing on the same window. In this lesson, we'll show how to navigate a component hierarchy and retrieve component values using scripting. So let's gen up a simple scenario showing all this here in our designer window. So we will drag a button from our palette and we'll drag an input spinner component right underneath it, like so. Note that we've got a couple of extra empty containers down here on the bottom, but we'll circle back around to these later, and finally, we will scroll down a bit to our writeable tags, expand that list, and scroll down to this WriteableInteger one. We'd like to use this button to trigger the read of a value on this spinner component, and then write that value to this WriteableInteger tag, pretty straightforward.
Let's start with the scripting for our button, so we will right-click on it and go to its scripting option, and then go to its action performed event handler. Now it's worth mentioning that for what we wanna do, we can certainly just use the set tag value builder and be done with it, but here we're trying to learn how to write the script ourselves. So instead we'll move on to the script editor tab on the right. So remember from the prior event object lesson, that event.source is just a pointer back to the source of the event, in this case, the button itself. Next, all components have a property on them also called .parent, which gives you access to the container a component is in. So here event.source.parent is pointing to the parent of the button, or here, the root container. Finally, containers then have a method on them called getcomponent, which takes a string as input and finds the child component you wanna find.
So event.source.parent.getComponent and in parentheses and double quotes, ("Spinner"), like so, is the child component of the root container which we are after. And that is how we traverse the component hierarchy by going up the tree from the button to the root container and then back down to the spinner like so. So now we can assign this entire expression for the spinner to a variable, so we can just do spinner equals all the stuff we've already got. Well, now this makes it easy to grab the value of the spinner. So now we can just say value = spinner, that entire expression on line one, .intValue, since we can simply use dot notation to pull any property out of any object in Python.
But wait a minute, how did we know that was the property value name we needed? There are two ways to find the specific scripting name of a property we need. For starters, we need to select the component and the designer to see its properties down here in the property editor. Then we will scroll down to the one we're interested in and here it's gonna be in the data section and it's gonna be this one, Value(Integer). So one way is to hover over it like so, and then this info pop-up appears and there we see that its property scripting name is intValue. Another way of doing the same thing is by selecting any property of interest like so, then clicking on this third property editor icon to show description area, then we can toggle this little information panel at the bottom, which also shows that its true scripting name is intValue, but I'll go ahead and close that up for right now.
Let's now return to our button scripting window by restoring it from the task bar like so. Now that we have our spinner value in our script, and we know now how to find it, remember that our end goal was to write it to our tag value. So to write to a tag, we can simply do this, system.tag.write, but we need the tag path to be able to do this, which we can get by right-clicking on the tag, going to its copy path, and then back in our scripting window, inside parentheses and double quotes, we will just paste that tag path, close it off, and then the second needed input is the value we wanna write, so simply the variable value. And so all this is how we'd write the value of the spinner to a tag from this button script.
This all looks good so far. Let's test it out. So we will click apply to save our changes, and then we'll go to the preview mode up here at the top. Then we'll set some value in the spinner. Let's say we'll set it to four and we'll click the button and we get an error. What this is telling us is we don't have the read/write mode set. Fair enough, so we'll close that and go back up here and go to read/write mode. Then let's try this again by clicking on the button, and then if we go down to our tag, we see that the value of the spinner was written to this tag upon the triggering event for the button press. It's worth noting at this point that if you have any custom properties on a component, they can be referenced in the same way, transparently, just like any other natural property. In that case, you'd simply use the name of the custom property instead of intValue back in the button scripting editor. Something we find often trips up newer scripters is how to navigate via scripting amongst multiple levels of containers.
So let's make some simple hierarchy changes to illustrate this. So we'll return to design mode up here at the top, and now I'll use these two containers from before. The left one is called BC for button container and the right one is named SC for spinner container. So we will relocate the two existing components. I will cut and paste the button into the left BC container, and then I'll cut and paste the spinner into the right SC container like so. So if we expand and look at our hierarchy in the project browser, we'll see that we've got a button inside a container inside the root container, and a spinner inside a container inside the root container, all the same as before, except with one new added container level, but we've also got a new problem now.
Let's open up our button's scripting option to see it. The script we had before isn't going to work anymore. Remember, event.source is the button, but now its parent is BC and BC doesn't have a child component spinner anymore. What we need to do now is go up one more parent level to the root container, so we will add one more .parent to our script. We can do this because, after all, containers are just special components and all components have a parent property. So now .parent.parent walks us up two levels in the hierarchy to the root container, and similarly, now we need to get components to get back down to the spinner. So what we'll add now is in between here, we will add a .getComponent("SC"), like so, and then its getcomponent leads us back to the spinner component.
Although this looks correct now, this can be kinda cumbersome to do. Now that we better understand the hierarchy as an alternate shortcut, what we can do to get the value is use the property reference button on the right. It lets us navigate the tree graphically, so we will go down to the spinner component and select the property intvalue, which is what we really wanted all along, and as you can see, it just does all of that work for us and yields the identical result so that we don't get lost as we try to walk up and down the component hierarchy. Let's quickly test out our changes by hitting apply to save our changes, and we'll go back to the preview mode and we'll set the spinner to a new value, maybe eight this time, and we hit the button and we see that our tag is indeed updated across the multiple levels as we expected to the new value, eight, from the spinner.
So in summary, what we've seen in this lesson is how to navigate a component hierarchy and scripting by using properties like .parent or methods like getcomponent.