Anvil Community Forum

How to trigger "Tab" keyboard key click from the code

Hi,

Is there straight forward way (custom component for example) to trigger “Tab” click or any other keyboard key using code. (I don’t have HTML or JS knowledge)
What I am trying to accomplish is to have a button “for example”, when this button clicked; the Tab key click event triggered, so the focus move to the next component. I read some posts about mousetrap, however, it does the opsite.

Please help, Thank you.

It depends on your components that need focus
if it’s TextBox and TextArea components you can call self.textbox.focus()

If it’s anything other than a TextBox or TextArea then i’d recommend

the code would look something like:

from AnvilAugment import augment

class Form1(Form1Template):
    def __init__(self, **properties):
        from itertools import cycle
        components = [self.componet1, self.component2, ..., ]
        for component in components:
            augment.add_event(component, 'focus')
        self.components = cycle(components)

    def button_click(self, **event_args):
        next(self.components).trigger('focus')
   

here’s a clone link:
I’ve added a bit more code just to make sure that the next element is always after the currently focused element but the premise is the same
https://anvil.works/build#clone:PZ2QKVDHB6TGANGY=VI5XYKST6HGIH3GHK727YBWM

1 Like

That is smart, however, what if the visibility/existence of the components on my form are dependent on specific actions of previous components? I made one of the components invisible and the focus still going to the invisible component. The other thing; if I change the order of the components in the design, it still going through list order.

Is there any way, you can click “Tab” key using the code, so the focus goes to the next component currently on the screen?

Thank you.

you could adapt the approach above for sure.

The order of the list will determine the order of tabbing so if the component orders don’t change on screen then it should be work… or have I missed something.

You can add flags into the loop, using the visible attribute or add a tag to the component that can be used in the loop to know whether to skip it or not.

The problem with replicating a tab key press on a button click is that as soon as you click the button to tabNext that button now has focus and so literally hardwiring tabNext would not go to the expected component. You’d have to do something like the above anyway I think… Or some other hack.

Possibly, but it will be a lot of work, and every change I do in future, I will have to go back and change this code again.

The issue with that is; what if the component added at run time (it is not exist in the list)? I can added it to the list at the run time, but the order will be different and hard to control (unless I write a lot of code)…etc.

The main Idea is to have a method when a drop_down item selected, the method moves the focus to the next component on the screen.

Something has to decide which is the “next” visual object. Leaving things to “the system” is not always best.

For example, when entering a table of numbers, “next” is typically the next number in the same column, not the same row. But most user interfaces will go left-to-right before they go top-to-bottom.

Sometimes, the best way to handle it is to just build (and maintain) an explicit list. Then “next” and “previous” are

  1. unambiguous
  2. exactly what you want them to be

instead of being whatever the platform happens to give you, like it or not.

I agree, but as you said “sometimes”. The method I am trying to create and call (to shift the focus to the next component) starts inside specific container and ends inside it, so it is somewhat controlled :grimacing:

I found some posts online using javascript like this one

body.onkeydown = function (evt) {
    var allowDefault = true;
    evt = evt || event;

    if (evt.keyCode === 9) {
        // tab was pressed
    }
    return allowDefault;
};

The problem is; I have zero javascript and HTML knowledge and I don’t really know how to use this code in anvil!

Sorry for being annoying :confused:

Not annoying at all! :slightly_smiling_face: To be fair, I worry that my posts may have annoyed for being too broad.

@p.colbert Your reply was informative :+1:, thank you!

Hi @david.wylie:

It would be great if you can explain how to call javascript functions (like press specific keyboard key event) from anvil, for someone like me who has limited understanding for javascript and HTML.

Thank you :blush:

As soon as your user interacts with the drop down that now has focus… so is the next element the one after the drop down? Or somewhere else on the screen? If it’s simply the next element then great. But if it’s not then :man_shrugging: how do we determine what the next element is?

i’ve updated the clone with another idea:
https://anvil.works/build#clone:PZ2QKVDHB6TGANGY=VI5XYKST6HGIH3GHK727YBWM

It utilises this library https://github.com/marklagendijk/jquery.tabbable
and adds four python functions tab_next, focus_next, tab_prev, focus_prev

it chooses the next available element from the flow_panel components so no hard coding of lists…

pseudo code

self.current = # component that last had focus in the flow panel
# it will lose focus as soon as we click next

def next_click(self, **event_args):
  if self.current is None:
    self.flow_panel.get_components()[0].trigger('focus')
  else:
    self.current.trigger('focus')
    tab_next()

2 Likes

That is super cool! Thank you :star_struck: