GWT – Adding a click handler to a DIV element

In jQuery, one popular way to create a simulated button is to create a stylized <div> element and then bind a click event handler to the <div> element like this:

<script src="jquery-1.6.2.min.js"></script>
<script>
$('#clickDiv').click( function() {
    alert("Div has been clicked");
});
</script>

<div id="clickDiv" style="padding: 5px; border: 1px solid black; cursor: pointer; width: 100px;">
    Click This Div
</div>

Since I am building an application in GWT, I knew there needed to be a way to do this “the GWT way” by using GWT event handlers.  This proved to not be as simple.  I started by putting the same <div> element in my UiBinder file:

<g:HTMLPanel>
    <div ui:field="clickDiv" class="{style.clickDiv}">
        Click This Div
    </div>
</g:HTMLPanel>

Then I created this UiHandler for the <div>:

@UiField
DivElement clickDiv

@UiHandler("clickDiv")
void handleClickDivClick(ClickEvent e) {
    System.out.println("Div has been clicked");
}

That caused this error when starting my application:

[ERROR] [myapp] - Field 'clickDiv' does not have an 'addClickHandler' method associated.

The error states that the GWT DivElement widget does not have an addClickHandler method.  So I knew I needed another widget.  As I have talked about in the past, the GWT documentation on panels and widgets is lacking.  For this situation, I was able to find the FocusPanel widget, which is exactly what I needed.  FocusPanel provides the ability to add a click handler along with other event handlers.  FocusPanel will be rendered as a <div>, so that meant I could change my UiBinder file to this:

<g:HTMLPanel>
    <g:FocusPanel ui:field="clickFormPanelDiv" class="{style.clickDiv}>
        Click This Div
    </g:FocusPanel>
</g:HTMLPanel>

And then change my UiHandler to this:

@UiField
FocusPanel clickFormPanelDiv;

@UiHandler("clickFormPanelDiv")
void handleClickDivClick(ClickEvent e) {
    System.out.println("Div has been clicked");
}

And just like that, I had a stylized <div> element that made use of a GWT event handler.

Advertisements

About stevewall123

I am a Lead Software Engineer in Minneapolis working for Thomson Reuters. I am currently working on projects using Java, JavaScript, Spring, Drools, Hazelcast, Liquibase and Tomcat. Previously, I used C#, GWT, Grails, Groovy, JMS and JBoss Drools Guvnor. In the past I have worked on projects using J2EE, Swing, Webwork, Hibernate, Spring, Spring-WS, JMS, JUnit and Ant.
This entry was posted in GWT, jQuery, UiBinder and tagged , , . Bookmark the permalink.

6 Responses to GWT – Adding a click handler to a DIV element

  1. This actually gives me an error: “Unexpected text in element: “Click This Div” Element ”

    Any idea why?

  2. Arek says:

    That’s true it works, but have you noticed that FocusPanel adds extra into your DOM? That’s quite weird in my opinion. I’m still searching a GWT panel that would do it without any extra elements…

  3. Arek says:

    Part of my post has been removed. There should be “FocusPanel adds extra input into your DOM”.

  4. Scott Bailey says:

    A few tips to help you simplify your code even more:

    In ui.xml files your root widget is not limited to HTMLPanel and can actually be any widget. In your example, you could change it to the following and still have it work correctly:

    Text

    This gets rid of one extra widget and the associated overhead of having it in the DOM.

    Another little known technique is that you can hook up event listeners to any arbitrary widget – you just need to forgo the @UiHandler annotation and setup the the event handler yourself using addDomHandler. As an example:

    @UiField HTMLPanel myWidget;

    private void setupHandlers() {
    myWidget.addDomHandler(
    new MouseOverHandler() {
    @Override
    public void onMouseOver(MouseOverEvent event) {
    // Do something.
    }
    },
    MouseOverEvent.getType());
    }

    In regards to Arek’s comment about FocusPanel adding an extra element into the DOM: my understanding with tinkering with it is that the hidden element is there for cross browser focus support. That is, detecting when focus and blur events occur on the input element then passing those elements onto the DIV. If you’re feeling adventurous, you can forgo the FocusPanel entirely and use HTMLPanel with a ClickEvent DOMHandler – but you’ll need to manually set it up yourself to be able to get focus events.

  5. HP says:

    Just been struggling with this as well. It is possible to attach the handlers without creating custom widgets or wrapping the div elements with a FocusPanel.

    e.g.

    if you have DivElement populated by a binding:

    @UiField DivElement myDiv;

    you can implement EventListener on the containing class, addding your own onBrowserEvent() handler.

    @Override
    public void onBrowserEvent(Event event)
    {
    switch(event.getTypeInt())
    {
    case(Event.ONCLICK):
    {
    if(myDiv.isOrHasChild(Node.as(event.getEventTarget())))
    handleMyDivClick(event);
    break;
    }
    }
    }

    The glue you need to get it to work is this code, somewhere in your init:

    Event.setEventListener(myDiv, this);
    Event.sinkEvents(myDiv,Event.ONCLICK);

    The Event types are bit fields, so you can listen for more events by ORing them:

    Event.sinkEvents(myDiv, Event.ONCLICK|Event.ONMOUSEOVER|Event.ONMOUSEOUT);

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s