I'm already using Alastair Maw's technique for attaching error messages to form fields. This visits all form components and attaches an error behavior to each one. This would be another behavior that would just be attached to the first editable form field. Turns out it works really well. I decided I only wanted to set focus on a text field or a dropdown, but you can decide for yourself.
public class ShinyFormVisitor implements IVisitor, Serializable
{
private static final long serialVersionUID = 9060018214520265174L;
private final Set<FormComponent> visited = new HashSet<FormComponent>();
private boolean found = false;
public Object component(Component c)
{
if (!visited.contains(c) && c instanceof FormComponent && !(c instanceof Button))
{
final FormComponent fc = (FormComponent) c;
visited.add(fc);
fc.add(new ValidationMsgBehavior());
fc.add(new ErrorHighlightBehavior());
if (!found && fc.isEnabled() && fc.isVisible() && (fc instanceof DropDownChoice || fc instanceof AbstractTextComponent))
{
found = true;
fc.add(new DefaultFocusBehavior());
}
}
return IVisitor.CONTINUE_TRAVERSAL;
}
}
In the above, a DefaultFocusBehavior is attached to the first form field of the right type. Now for DefaultFocusBehavior itself:
/**
* @see http://www.nabble.com/Default-Focus-Behavior--td15934889.html
*/
public class DefaultFocusBehavior extends AbstractBehavior
{
private static final long serialVersionUID = -4891399118136854774L;
private Component component;
@Override
public void bind(Component component)
{
if (!(component instanceof FormComponent))
{
throw new IllegalArgumentException("DefaultFocusBehavior: component must be instanceof FormComponent");
}
this.component = component;
component.setOutputMarkupId(true);
}
@Override
public void renderHead(IHeaderResponse iHeaderResponse)
{
super.renderHead(iHeaderResponse);
iHeaderResponse.renderOnLoadJavascript("document.getElementById('"
+ component.getMarkupId() + "').focus();");
}
}
0 comments:
Post a Comment