Set focus on a component with Apache Wicket?
Asked Answered
P

7

7

How do you set focus on a component with Apache Wicket? Searching leads to very little information, mostly on setting the default field. I do not want to set a default field, rather I am looking to set focus when, for example, a specific radio button is selected.

Paternalism answered 13/4, 2010 at 19:46 Comment(0)
R
8

Once you create your behavior to set the focus, you should be able to add it to the component on any event, just make sure that component is part of the AjaxRequestTarget. I don't see why this wouldn't work...

myRadioButton.add(new AjaxEventBehavior("onchange") {
 @Override
 protected void onEvent(AjaxRequestTarget target) {
    myOtherComponent.add(new DefaultFocusBehavior());
        target.addComponent(myForm);
 }
});

Here's a link that shows how to create the default focus behavior if you do not have one already: http://javathoughts.capesugarbird.com/2009/01/wicket-and-default-focus-behavior.html

Recipience answered 14/4, 2010 at 2:22 Comment(2)
I'd suggest you to copy the code into the answer (keeping the original reference, of course), so that it doesn't depend on external resources.Licit
problem with this solution is that once you attached it then everytime it is refreshed (AjaxRequestTarget#addComponent) it's focused (or at least focus javascript is evaluated) using AjaxRequestTarget#focusComponent is one shot focus so it's better suited for behaviour requested in question ("radio button is selected")Convection
H
20

I suggest using the native org.apache.wicket.ajax.AjaxRequestTarget#focusComponent(). For example:

/**
 * Sets the focus in the browser to the given component. The markup id must be set. If            
 * the component is null the focus will not be set to any component.
 * 
 * @param component
 *            The component to get the focus or null.
 */
 org.apache.wicket.ajax.AjaxRequestTarget#focusComponent(Component component)
Huynh answered 10/4, 2012 at 10:48 Comment(2)
Listen to what martin-g says ;-)Maxine
martin-g's solution was the only solution that got it working for my scenario - a modal/pop up. I think autofocus only works on page load, not modal load so any efforts to skillfully set the autofocus attribute in the HTML just fail miserably - always. Make sure you call myInput.setOutoutMarkupId(true) and then override show(ART target) { super.show(target); target.focusComponent(myInput) } Works like a bought one! Maybe I'll do a full answer.Wendel
R
8

Once you create your behavior to set the focus, you should be able to add it to the component on any event, just make sure that component is part of the AjaxRequestTarget. I don't see why this wouldn't work...

myRadioButton.add(new AjaxEventBehavior("onchange") {
 @Override
 protected void onEvent(AjaxRequestTarget target) {
    myOtherComponent.add(new DefaultFocusBehavior());
        target.addComponent(myForm);
 }
});

Here's a link that shows how to create the default focus behavior if you do not have one already: http://javathoughts.capesugarbird.com/2009/01/wicket-and-default-focus-behavior.html

Recipience answered 14/4, 2010 at 2:22 Comment(2)
I'd suggest you to copy the code into the answer (keeping the original reference, of course), so that it doesn't depend on external resources.Licit
problem with this solution is that once you attached it then everytime it is refreshed (AjaxRequestTarget#addComponent) it's focused (or at least focus javascript is evaluated) using AjaxRequestTarget#focusComponent is one shot focus so it's better suited for behaviour requested in question ("radio button is selected")Convection
S
3

If you only want to setFocus through javascript and don't want to reload a form or a component, you can use the following code:

import org.apache.wicket.Component;

public class JavascriptUtils {
    private JavascriptUtils() {

    }

    public static String getFocusScript(Component component) {
        return "document.getElementById('" + component.getMarkupId() + "').focus();";
    }
}

And then in any Ajax Method you can use:

target.appendJavascript(JavascriptUtils.getFocusScript(componentToFocus));
Saraisaraiya answered 20/4, 2010 at 22:7 Comment(0)
S
1

For a pop-up like modalWindow my workaround solution was to use the attribute "autofocus" on the first input tag. An easy solution is to add it to the html directly.

<input ..... autofocus>

Another solution is to add it to the modalWindow itself:

@Override
public void show(AjaxRequestTarget target) {
    super.show(target);
    setUpFocus();
}

protected void setUpFocus() {
    DeepChildFirstVisitor visitor = new DeepChildFirstVisitor() {

        @Override
        public void component(Component component, IVisit<Void> iVisit) {
            if (isAutofocusable(component)) {
                component.add(new AttributeAppender("autofocus", ""));
                iVisit.stop();
            }
        }

        @Override
        public boolean preCheck(Component component) {
            return false;
        }
    };
    this.visitChildren(FormComponent.class, visitor);
}

    protected boolean isAutofocusable(Component component) {
        if (component instanceof TextArea ||
                component instanceof DropDownChoice ||
//                component instanceof RadioChoice ||
                component instanceof AjaxCheckBox ||
                component instanceof AjaxButton || 
                component instanceof TextField) {
            return true;
        }
        return false;
    }

RadioChoice is commented out because this solution is not working on that. For RadioChoice i would recommend to implement a FocusedRadioChoice:

public class FocusedRadioChoice<T> extends RadioChoice<T> {
//constructors...
    @Override
    protected IValueMap getAdditionalAttributes(int index, T choice) {
        super.getAdditionalAttributes(0, choice);
        AttributeMap am = new AttributeMap();
        am.put("autofocus", "");
        return am;
    }
}
Seal answered 2/8, 2016 at 7:52 Comment(1)
Neither of these solutions work for me: either setting autofocus directly in the HTML or using the code above to use the attribute appender to set the focus. I think, maybe, the autofocus attribute only works on page load, not on modal dialog load?Wendel
B
0

Is there a way to achieve the same without JavaScript?

(I am implementing a form with a feedback-Panel that only comes up when Javascript is turned off, so it would not make sense to depend on JavaScript there...,-)

I could only find answers which use JS .focs()... maybe Wicket 1.5 will provide a method Component.setFocus()...

Bowman answered 15/12, 2010 at 9:58 Comment(2)
There is no way to set focus to an html element without using JavaScript. HTML doesn't have a tag or attribute that would enable this (yet). If Wicket ever implemented a Component.setFocus() method it would still generate some JavaScript to enable it.Saraisaraiya
You can use the simple html attribute "autofocus". You can directly add it to the html's first input tag or dinamically add like "component.add(new AttributeAppender("autofocus", ""));" Check my brief answer.Seal
F
0

If you happen to be using an Ajax button, you can simply call target.focusComponent(myComponent); in the button's onSubmit method.

Forthcoming answered 3/4, 2012 at 10:44 Comment(0)
W
0

@martin-g 's solution was the only solution that got it working for my scenario - a modal/pop up.

Note: I think autofocus embedded explicitly in HTML only works on page load, not modal load so any efforts to skillfully set the autofocus attribute in the HTML of a modal just fail miserably - always.

Here I lay out the steps for setting the focus on an input field called 'myInput' using the full power of Wicket (no JS!):

In onInitialize:

// Make sure the field has an ID in markup
myInput.setOutoutMarkupId(true);

Provide an overridden show method where you call the focusComponent method:

public void show(AjaxRequestTarget target)
{
    // Make sure you call the super method first!
    super.show(target);

    target.focusComponent(myInput);
}

This does require that your component is an attribute of your modal content class so that you can access it in the show method. To avoid creating a class attribute for your input component you could blend this solution with the solution from BlondCode by replacing that solution's

component.add(new AttributeAppender("autofocus", ""));

with

target.focusComponent(component);

This also works!

Wendel answered 29/4, 2020 at 4:14 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.