Mechanics of nested buttons [Back to index]
Since 2019-09-12T22:00:00Z buttons can no longer be nested. There is a petition to bring this feature back, but for now all of the information below is deprecated.
With the Button()
formula, you can put a button into a label of another button (which is in a label of another button and so on).
This kind of nested buttons have a few useful and interesting properties.
Action execution order
When you click on a nested button, it will firstly execute the action of the button you directly clicked.
Then it will execute the action of its parent, and then a parent of the parent, and so on until it reaches the root.
That means that if you were to click the blue button from the image above, action order would be
blue --> green --> yellow --> white
, with white overwriting any colliding actions (like changing value of the same row and column).
There is just one big problem - those actions are asynchronous.
That means that they start executing in this order, but the changes may be applied in a completely different one, based on the complexity of the action.
This is fragile to such an extent that just wrapping a formula with RunActions()
or adding an if statement (even if it is just If(true,"","")
) will change this order.
That means that this order is only reliable when the actions are nearly identical (for example: ModifyRow()
with static target, column and value).
Activating only the top button
Clicking only the top-most button can be useful in many cases and it can actually be achieved.
Because of the execution order, when a button action is executed you can check if any other button was clicked earlier. If it was, it means it was above this one.
To do that, you would need to wait (using _Delay()
) until the previous action is executed and check if there were any changes using Modified()
.
While it is possible to create this for more than 2-deep buttons, the delay would stack up and make the buttons pretty slow and impractical. So I’m only going to explain how to achieve that with 2-deep buttons.
The problem is that we need to make sure the background button detects the top button being clicked, even if it has a slow formula.
To do that we can simply change the formula of the top button to
RunActions(
ModifyRows(thisRow, [Button detection], "W"),
<the actual formula>
)
This makes sure that the change will be detectable at the same time after the button is clicked, no matter what the complexity of the formula actually is.
Detecting the button change is also tricky.
Because of how the _Delay()
formula works, you have to split the action into two buttons.
The first one (the one you actually click) should look like this:
_Delay([Actual action],300)
And the second one should look like this:
if(Now()-Modified(thisRow.[Button detection])<=Seconds(0.35),"",
<the actual action>)
You may be tempted to set the button detection
column to Now()
when clicking first button, but not only is that value rounded (and basically useless) it will also create a lot of other problems.
Note that you don’t need to use those exact delays, those are just the ones I found reliable.
One more issue
There is still one small issue with this solution - if you click the bottom button fast enough after clicking the top button, the bottom button won’t be activated.
This can be easily fixed by changing the formula of the bottom button to
if(IsNotBlank(thisRow.[Button detection]) &&
Now()-Modified(thisRow.[Button detection]) <= Seconds(0.35),
ModifyRows(thisRow,thisRow.[Button detection],""),
<the actual action>
)
Sandbox