views:

38

answers:

2

I'm trying to pass my app's EventBus to a widget declared in a UiBinder via its constructor. I'm using the @UiConstructor annotation to mark a constructor that accepts the EventBus, but I don't know how to actually reference the object from my ui.xml code.

That is, I need something like

WidgetThatNeedsAnEventBus.java

public class WidgetThatNeedsAnEventBus extends Composite
{
    private EventBus eventBus;

    @UiConstructor
    public WidgetThatNeedsAnEventBus(EventBus eventBus)
    {
        this.eventBus = eventBus;
    }
}

TheUiBinderThatWillDeclareAWTNAEB.ui.xml

<g:HTMLPanel>
    <c:WidgetThatNeedsAnEventBus eventBus=_I_need_some_way_to_specify_my_apps_event_bus_ />
</g:HTMLPanel>

I have no problem passing a static value to the WidgetThatNeedsAnEventBus, and I can use a factory method to create a new EventBus object. But what I need is to pass my app's already-existing EventBus.

Is there a way to refer to already-existing objects in a UiBinder?

+1  A: 

I'd suggest you use a factory method (described here). This way you can pass an instance to your widget.

With the <ui:with> element you can also pass objects to widgets (provided a setter method exists) (as documented here). But the object will be instantiated via GWT.createwhich I think is not was you intend doing with the eventBus.

z00bs
also a good example for factory methods: http://blog.jeffdouglas.com/2010/02/24/gwt-uibinder-passing-objects-to-widgets/
z00bs
I don't want to instantiate a new object, as it seems like a factory method would require. Here's a different example: let's say I have a String called myString, and in a ui.xml file I have a <g:Label /> declared. How can I specify to that <g:Label> that it should use the Label(String) constructor, and pass the value of myString to that constructor? @UiField(provided=true) looks promising, but I can't see how to pass myString to a constructor. Perhaps this is not possible with UiBinder?
Riley
Passing a string: create and annotate the constructor of your ui class with `UiConstructor` and in the ui.xml file define an attribute with exactly the same name as the constructors argument. `public @UiConstructor MyWidget(String myString)` and `<my:MyWidget myString="foo" />`.
z00bs
Me again :). Since reading your question I'm curious why you wanna pass the eventBus via the ui.xml? If you're developing your app the MVP style I'd suggest the presenter is the class that should know about the bus, in some cases maybe also the widget. But why the presentation at all? I'm sure you have your reasons, so another possibility could be to pass the bus from one widget to another. Have a look at http://blog.jeffdouglas.com/2010/02/05/gwt-uibinder-passing-parameters-to-widgets/.
z00bs
Thanks for your work, but the problem is that I want to pass an object that already exists, not create something new (like "foo.").
Riley
A: 

My eventual solution was to use @UiField(provided=true) on the widget I needed to initialize with a variable.

Then, I just constructed the widget myself in Java, before calling initWidget on the parent.

For example:

public class ParentWidget extends Composite
{
    @UiField(provided=true)
    protected ChildWidget child;

    public ParentWidget(Object theObjectIWantToPass)
    {
        child = new ChildWidget(theObjectIWantToPass);  //_before_ initWidget
        initWidget(uiBinder.create(this));

        //proceed with normal initialization!
    }
}
Riley