not able to set focus on TextBox in a GWT app - gwt

This should not be causing me so much pain but it is. It is a very weird problem. In a GWT application, I have two .java files, login.java and application.java.
In login.java, I'm creating a user login page where if the username and password is verified the user is logged into the application and application.java takes from here.
Now in application. java's onModuleLoad() this is how i'm starting with a login page.
public void onModuleLoad() {
Login login = new Login();
login.textBoxUsername.setFocus(true);
RootLayoutPanel.get().add(login);}
This works great, except for the tiny problem of not being able to set focus on the username TextBox when the page loads. I have tried evrything I can think of. But the focus just doesn't get set on the TextBox. If anyone can suggest a solution, please do. Your help is greatly appreciated.
Solution: (In case it helps anyone facing the same issue)
final Login login = new Login();
Scheduler.get().scheduleDeferred(new ScheduledCommand() {
public void execute () {
login.textBoxUsername.setFocus(true);
}
});
RootLayoutPanel.get().add(login);

Try using Scheduler.scheduleDeferred():
public void onModuleLoad() {
Login login = new Login();
Scheduler.get().scheduleDeferred(new Scheduler.ScheduledCommand () {
public void execute () {
login.textBoxUsername.setFocus(true);
}
});
RootLayoutPanel.get().add(login);
}
Update: answer updated to use Scheduler.get().scheduleDeferred() instead of DeferredCommand, which is deprecated.

Why using DefferedCommand, I think it's better to use someWidget.getElement().focus() which is a native Javascript. I'm using it everywhere, I've not seen any problem.

If your Widget extends Composite, you can:
#Override
protected void onAttach() {
super.onAttach();
textBoxUsername.setFocus(true);
}

It would be so easy for GWT to store a 'wantsFocus' in the internal state, and call focus after the widget is attached. We are still waiting after many years for that feature however...
Still, even after the attach handler is called, setFocus does not always work.
So in the meantime, our GwtUtil library has used the following code. It is a combination of several other solutions, and has been wrapped in a utility function:
static public void setFocus(final FocusWidget focusWidget) {
if (focusWidget.isAttached()) {
Scheduler.get().scheduleDeferred(new Scheduler.ScheduledCommand() {
#Override
public void execute() {
focusWidget.setFocus(true);
}
});
} else {
focusWidget.addAttachHandler(new AttachEvent.Handler() {
#Override
public void onAttachOrDetach(AttachEvent event) {
if (event.isAttached()) {
Scheduler.get().scheduleDeferred(new Scheduler.ScheduledCommand() {
#Override
public void execute() {
focusWidget.setFocus(true);
}
});
}
}
});
}
}
And call it like this:
setFocus(myTextBox);
It makes sense to use a utility function; If and when GWT finally makes setFocus work, you won't have to change your source code in multiple places.

Related

How to get an editable ComboBox to respond to ENTER

This code is what I want to do. While typing in an editable ComboBox I want to release ENTER and handle that enter event. However, I cannot get the application to respond, a message was not printed. I wrote basically the same code for a text box and it worked fine, a message was printed. I also wrote the handler for any KeyReleased event for a ComboBox and that worked fine also, a message was printed. The trouble is the enter key. Why does this code not do what I want in an editable ComboBox?
#FXML
ComboBox comboBox;
public class ScreenController implements Initializable {
#Override
public void initialize(...) {
...
comboBox.setOnKeyReleased(new EventHandler<KeyEvent>() {
#Override
public void handle(KeyEvent ke) {
if (ke.getCode == KeyCode.ENTER) {
System.out.println("ENTER was released");
}
}
});
}
}
I was suffering from the same bug/feature. Luckily I found this posting
The solution is not to register your handler via comboBox.setOnKeyReleased(). instead, use EventFilter:
comboBox.addEventFilter(KeyEvent.KEY_RELEASED, new EventHandler<KeyEvent>() {
#Override
public void handle(KeyEvent ke) {
if (ke.getCode == KeyCode.ENTER) {
System.out.println("ENTER was released");
}
}
});
This actually works as expected.
It's look to be a JavaFX bug. setOnKeyPressed doesn't work to. look at this
javafx jira

How to call GWT client code from within a GQuery event handler?

I'm learning GQuery. It seems cool, but also a little confusing.
I have the following GWT client code. The selected item fades out, nicely. But the delete method never gets called. There is no error. It's very odd.
Is it even possible to call non-GQuery functions from inside a GQuery method?
delete.addClickHandler( new ClickHandler() {
#Override
public void onClick(ClickEvent event) {
$(myIndicator).fadeOut(500, new Function(){
#Override
public void f() {
super.f();
delete();
}
});
}
});
And the delete method is:
private void delete() {
removeFromParent();
ruleDeleteRequestEvent.fire(new RuleDeleteRequestEvent(ruleBinder.getModel()));
}
Do not call super.f(), if so the default implementation of Function.f() will throw an Exception preventing the next line be executed (take a look to the source code) .

ClickHandler doesn't fire in jquery-mobile header & footer

after hours of searching and trying, I decided to ask here.
JqmHeader.java
public class JqmHeader extends ComplexPanel {
public JqmHeader() {
setElement(DOM.createDiv());
getElement().setAttribute("data-role", "header");
}
public void add(Widget widget) {
super.add(widget, getElement());
}
}
JqmPage.java
public class JqmPage extends ComplexPanel {
...
public JqmPage(String id) {
setElement(Document.get().createDivElement());
getElement().setAttribute("data-role", "page");
getElement().setAttribute("data-url", id);
RootPanel.get().add(page);
render(page.getId());
}
private native void render(String id) /*-{
$wnd.$("#" + id).page();
}-*/;
...
}
MyPage.java extends JqmPage.java
...
JqmHeader header = new JqmHeader();
Button b = new Button("TestButton");
b.addClickHandler(new ClickHandler() {
#Override
public void onClick(ClickEvent event) {
Window.alert("TestButton clicked");
}
});
header.add(b);
this.add(header);
...
My Problem
So, my Problem is, that the ClickHandler from the Button in the header bar doesn't fire. If I add the Button not to the header, but to the "RootPage", like
this.add(b)
, everything works.
I think it must lie at the jquery-mobile header implementation. Are there any workarounds /ideas?
Thanks from Berlin,
Alex
JQuery Mobile swallows the events on headers so they are not propagated to GWT. What I did in solving this for jqm4gwt (https://github.com/sksamuel/jqm4gwt) was to have a general listener on the page level and then compare event source. If it was a button in the header then I fire that event on the button manually.
Take a look at bindHeaderEvents in https://github.com/sksamuel/jqm4gwt/blob/master/src/main/java/com/sksamuel/jqm4gwt/JQMPage.java
Also, the jqm4gwt project might be a good solution for you to save you having to invent all these widgets yourself.
If you want to take a look at a pure GWT solution for building mobile apps you could take a look at http://www.m-gwt.com

GWT is making an unexpected event call

My code is below: I am seeing that on running the app the loadWidget method gets invoked even when the adminLink is not clicked. This is not want I want, but I'm not sure what is causing the issue. Please advise
public class LoginModule implements EntryPoint {
LoginPopup loginPopup;
private class LoginPopup extends PopupPanel {
public LoginPopup() {
super(true);
}
public void loadWidget(){
System.out.println("I am called 1");
CommonUi cUi = new CommonUi();
//#342 moved code to common area
FormPanel loginForm = cUi.getLoginFormUi();
setWidget(loginForm);
}
}
#Override
public void onModuleLoad() {
//#251 improved login popup ui.
final Anchor adminLink = new Anchor("User Login");
// final Label adminLink = new Label("User Login");
adminLink.addClickHandler(new ClickHandler() {
public void onClick(ClickEvent event) {
// Instantiate the popup and show it.
loginPopup = new LoginPopup();
loginPopup.loadWidget();
loginPopup.showRelativeTo(adminLink);
loginPopup.show();
}
});
if(RootPanel.get("admin") !=null)
RootPanel.get("admin").add(adminLink);
}
}
Running Dev Mode, set a breakpoint in that method in your Java IDE, and take a look at the current stack, what code is calling that method. If that is the only code in your app, then this only appears to be invokable from that onClick handlers, so it is a matter of figuring out why that is being invoked.

continueToOriginalDestination does not bring me back to originating page

I am trying to sign into my application. First I throw the RestartResponseAtInterceptPageException (this is in a WicketPanel on my BasePage):
add(new Link<String>("signin") {
#Override
public void onClick() {
throw new RestartResponseAtInterceptPageException(SignIn.class);
}
});
The SignIn Page class contains a form (an inner private class) for the sign in, with the following submit button:
add(new Button("signinButton") {
#Override
public void onSubmit() {
final User user = model.getObject();
final boolean result = MySession.get().authenticate(user);
if (result) {
if (!continueToOriginalDestination()) {
setResponsePage(MySession.get().getApplication().getHomePage());
}
} else {
error("Authentication failed");
}
}
});
When this button is clicked and the user is successfully authenticated, I am not redirected to the page where I clicked on the signIn link but instead I stay on the SignIn page? I've tried debugging this, but haven't been able to find out where things go wrong.
I am glad for any hints that lead to my finding the error of my ways.
This is wicket 1.5.1 by the way.
Small Update because I got the hint I needed from the answer, there is still a bit of explaining to do. The solution looks like this:
add(new Link<String>("signin") {
#Override
public void onClick() {
setResponsePage(new SignIn(getPage()));
}
});
The SignIn class gets a constructor that takes a page obviously and I simply set that page as with setResponsePage to return to where I started without all the continueToOriginalDestination and exception throwing.
RestartResponseAtInterceptPageException is meant to be used to redirect to an interception page while rendering a page. For example, in the constructor of a Page class ProtectedPage, if there is no user signed in, you throw new RestartResponseAtInterceptPageException(SignIn.class). When the SignIn page calls continueToOriginalDestination(), the user is taken back to the original ProtectedPage destination.
Your use is not a typical use of RestartResponseAtInterceptPageException since you throw it in a link handler. Why don't you do a setResponsePage(SignIn.class) directly instead? If you really want to return to the exact page you were on when the "signin" link is clicked, you could also try changing it to:
add(new Link<String>("signin") {
#Override
public void onClick() {
setResponsePage(getPage());
throw new RestartResponseAtInterceptPageException(SignIn.class);
}
});