How to manage TabIndex with multiple layouts

Hi,

Does anyone manage to handle complex screen with isolated tab indexes properly? Assuming a screen hold 3 “forms” (i.e. a bunch of fields and maybe buttons) and has dedicated tab indexes on each form. When the screen is implemented, the order between each of these form is known.

What I’d like is to be able to implement these “forms” isolated to which screen they will be added. In other words, I don’t want to put a tab index that is dependent on the order of these forms in the screen.

Ideally, I would add 1, 2, 3, 4 for my first form, 1,2,3 for my second form and 1,2,3,4,5 for my third form. And the one that designs the screen would say which form should come first. For instance, first form, third form and second form. This should give something like 1,2,3,4 for the first form, 10,11,12 for the second form and 5,6,7,8,9 for the third form. That way, the index for that screen is like the one expected and I don’t have to deal with these details at the “form” level.

With plain Vaadin, that sounds very hard to do but maybe others have tried different solutions.

Thanks.

It wasn’t “very hard” and I don’t know if our scheme was the best, but we did it just by passing in the ‘start tab index’ to our sub-Forms. And rather than worry about keeping them all in perfect order with no gaps and no two fields having the same value (which is okay, but then field order in the DOM matters and that order doesn’t appear to be preserved by the order of properties specified in param 2 of Form.setItemDataSource), we’d just increment the tab index by the maximum number of fields a sub-Form could have even if it had variable numbers of fields. And we set the value (plus an increment) in the DefaultFieldFactory.createField() callback since the order the fields are created does match setItemDataSource properties order (so our tab order was the same as the property order).

Another possibility - which I’ve not done myself, as we’ve not needed it yet - would be to maintain a “next tab ID” at the window level.
Override the Form#attach method (or the containing component) and then iterate through the local fields e.g.


public void attach(){
   int count = 0;
   int nextTabID = getWindow().getNextTabID()
   for each c in getComponents
      count++;
      c.setTabIndex(c.getTabIndex + nextTabID - 1)
   next
   getWindow().setNextTabID(nextTabID + count)
}

public void detach(){
   /* Well, reverse of attach! */
}

So, each of the “subForms” maintains a tabIndex relative to 1; attaching and detaching changes the order relative to the windows “next tab ID”.
Actually, detach might be a bit tricky, depending on the order that detach works - you might need to add something to the Window to work out the last usable tabID from all it’s children, and update it on every detach.

There are almost certainly better ways to do this, or refinements, but I’m pretty sure that doing stuff on atttach/detach would be not too invasive and good starting point.

Cheers,

Charles.

Thanks, I’ll investigate that.

Maybe I did not read this carefully enough, but I don’t think you need to do anything in detach - if I remember correctly, it is ok to leave gaps in the tab index sequence.

Don’t forget to call super.attach() and super.detach() if overriding those methods!

So what I have now is a “focusIndex” setting that can be set on any component. Each “form” (e.g. layout) can be defined independently and have local focus index. When multiple layouts are added in a screen, one can set a priority by setting a focus index on the layout.

There is a focus index manager that is taking care of walking the tree and identifying the zone that needs to be resolved. Once the zone are resolved (with the list of Focusable components having a focus Index), it computes the actual tab index and set them.

This is something you could add in attach indeed even though we are a bit smarter since we can identify if a component is attached with a focus index and recompute the index at that time.