How to set focus in Form component

Hi everyone,

I am looking for a way to manage focus within a Form component. I have several text input fields and I need to populate them using a barcode scanner configured as a keyboard wedge. Proper focus management is crucial for this application. I am using a Honeywell CT37 Android device with a built-in scanner.

I am struggling with two specific issues:

  1. Initial Focus: When the screen opens, no field in the Form has focus by default. I have to manually click on a field to start scanning. Is there a way to auto-focus a specific field on view startup? I have already tried self.focus() in Form startup event but it doesn’t work.
  2. Focus Progression after Scan: When using a regular keyboard, pressing Enter or Tab moves the focus to the next field as expected. However, when using the scanner, the value is entered, but the focus remains on the current field. The scanner is configured to send a \r (Carriage Return) character after each scan, but the Form doesn't seem to trigger the focus change.

My Form setup is shown below:

The ideal solution for initial focus would be a view “onLoad” handler that would fire when the view is done loading, which doesn’t exist yet (vote for it here).

Instead, you’ll have to use the onStartup handler of the view, which may fire before the input you want focused is rendered, and use a sleep() delay:

def runAction(self):
	import time
	
	time.sleep(0.5)	# wait half a second
	self.focus()

Hi Ryan,

Thanks for the suggestion. However, the onStartup event doesn't seem to be the core issue here.

To test this, I added a "Test Button" to the screen to attempt to set focus manually once the View is fully loaded. In the onActionPerformed event of the button, I used the following script:

def runAction(self, event):
    self.getSibling("Form").focus()

Even with this manual trigger, the focus is not being set to the Form (or the specific input field within it). It seems like calling .focus() on the Form component itself doesn't automatically delegate focus to its internal input fields.

Do I need to target the specific input component inside the Form directly, or is there a known limitation with focus delegation in the Form component?

Focusing the Form component is not the same as focusing an input component within it. You’ll need to target that specific component (I would apply an onStartup handler on the specific component).

Sure. Focusing the Form is not same as focusing a component within the Form, but I don’t know how to focus specific component within Form.
If I try to call:

# try to focus first text field within the Form
self.getSibling("Form").props.columns.items[0].rows.items[1].widgets[0].focus()

then it throw AttributeError: 'com.inductiveautomation.perspective.gateway.script' object has no attribute 'focus'

Well again, I would just use an onStartup handler:

But if you want to activate it some other way, you could have a button or whatever invoke system.perspective.sendMessage() and use a message handler instead. I don’t recommend ever using getSibling/Child/Parent() because such scripts will break if you ever start rearranging the layout.

But You are talking about Text field and I’m talking about Form. Form component is new in Ignition 8.3

Oh, sorry, I haven’t used that yet and didn’t realize it doesn’t use nested components. But I image the tabIndex order of the “widgets” should determine which input is focused initially. The default is 0, so if that’s what they’re all set to, you’d need to make sure only the one you want focused is set to that.

BTW, if you chose the Form component in order to eventually support offline mode, be aware that offline mode won't run any UI event scripts.

I know that in offline mode UI event scripts are not working and I can live with it. But I’m not able to set focus to Form even online.

Currently, there is not a way to handle this scenario (set focus to a specific field on load or field change) in the Form Component. I’ll get a feature request written up to add this functionality.

2 Likes