How to expose table widget to presenter in MVP pattern with gwt - gwt

In MVP pattern the widget (the view) exposes its widgets in form like this:
#Override
public HasClickHandlers getAddIssueClickHandlers() {
return addIssueButton;
}
and like:
#Override
public HasText getTaskName() {
return taskName; // taskName is a Label
}
To allow the presenter to modify the view or get the values from a widget. However, its uncertain how to get a table widget, like FlexTable or CellTable in order for the presenter to modify the table. Any ideas is much appreciated. Thanks.

Not all GWT widgets were designed with these interfaces (i.e. HasclickHandlers, HasText, IsWidget, etc) in mind.
In recent GWT versions the basic widgets were changed so that they implement these interfaces in order to make the views which use them testable in unit tests. So I am not sure if the FlexTable implements these interfaces but in case of CellTable you can use the HasData interface.
Here you can find the interfaces that are implemented by the CellTable: Javadoc
I personally would expose the CellTable via the HasData interface, which can be used to set and retrieve the selectionModel (for selecting rows in the CellTable).
For modifying or updating the data that is displayed in the CellTable, I would use a ListDataProvider and store it in the Presenter.
#Override
public HasData getCellTableDisplay() {
return cellTable;
}
and in the constructor of the presenter
you can create a ListDataProvider and use the addDataDisplay function to add the CellTable:
final ListDataProvider<String> dataProvider = new ListDataProvider<String>();
dataProvider.addDataDisplay(getView().getCellTableDisplay);

Related

What exactly DataProvider does with respect to CellTable in GWT

I am beginner in GWT application development. I have searched about CellTable online. Didn't got any explaination other than some examples.
Now I really want to know what exactly the DataProvider does in CellTable?
Also would like know more about celltable and if there are any resources available for the same??
The dataprovider holds your model.
Whenever you change your model (for instance, a list of object mapped to your cellTable), it will be in charge of updating the display.
It acts as a controller between your display (the cellTable) and the model (i.e. a list of objects, typically a list of shared objects coming from your back-end).
Here is an example with a listdataprovider:
#UiField(provided = true)
protected CellTable<TableRowDataShared> cellTable;
protected ListDataProvider<TableRowDataShared> dataProvider = new ListDataProvider<TableRowDataShared>();
public void init() {
dataProvider.addDataDisplay(cellTable);
// init your cellTable here...
}
public void onModelUpdate(List<TableRowDataShared> newData) {
dataProvider.getList().clear();
dataProvider.getList().addAll(newData);
dataProvider.flush();
dataProvider.refresh();
cellTable.redraw();
}

How to force GWT to add unique ID to each DOM element?

I am having a GWT app,
I would like to add ID to each element automaticlly
if it's impossible, what would be the fastest way to do it manually?
I am not so sure about performance issues. How would adding a dew ids in a form of 10-20 widgets cause performance loss?
To automagically set debug ids on widgets you need to include following in your module.gwt.xml file.
<!-- Enable debug ID. -->
<inherits name="com.google.gwt.user.Debug"/>
<set-property name="gwt.enableDebugId" value="true"/>
You can create your own Widget class that extends GWT Widget and sets an id to each one:
public class myWidget extends Widget {
public myWidget(String id) {
super();
getElement().setId("id");
}
public void setId(String id) {
// Use this method if you use Ui:Binder
getElement().setId("id");
}
}
You can, obviously, extend other classes instead of Widget if you don't need id on all widgets, like FlowPanel, Button, etc.
If you want to have an element to have an Id always, you can go with ensureDebugId of UI Object class. It make sure that, your element have an Id set before attaching it to the dom.
Yes its Possible :
First way:
Button b = new Button();
DOM.setElementAttribute(b.getElement(), "id", "my-button-id")
Second way :
FlowPanel panel = new FlowPanel();
panel.getElement().setId("my-flowpanel-id");
If you want to do assign all the id's attached to DOM you can do
Iterator<Widget> iterator = RootPanel.get().iterator();
while(iterator.hasNext()) {
Widget w = iterator.next();
w.getElement().setId("id");
}

Custom Composite widget in *.ui.xml

I would like to create a custom GWT composite widget that I can later use this way in *.ui.xml using uiBinder (cw is prefix for my custom widgets package):
<cw:CustomPanel>
<cw:header><g:Label>test</g:Label></cw:header>
<cw:content><g:Label>test</g:Label></cw:content>
</cw:CustomPanel>
In short, I would expect that setHeader and setContent methods on my custom widget are called by the framework somehow.
Is that at all possible?
This is what #UiChild is for, see the JavaDoc at http://google-web-toolkit.googlecode.com/svn/javadoc/latest/com/google/gwt/uibinder/client/UiChild.html
If you want to keep the method names setHeader and setContent (instead of addHeader and addContent), you'll have to use
#UiChild(tagname = "header")
void setHeader(Widget headerWidget) {
...
}
Create setHeader(String title) and setContent(String content) methods in your widget's Java class. In these methods add text to your header and content panel respectively. Then you can use this widget in Ui:Binder this way:
<cw:CustomPanel header="test" content=test" />

How to create CellTree with MVP pattern

As suggested in gwt documentation, I try to follow the MVP design pattern while creating my application. When using simple tree, the example in the documentation is straight forwards and makes good example of MVP and gwt. In the example the view is created and the data is given to the view to display. As far as I understand this is exactly the way to keep view, model and presenter separated.
With CellTree, the data populating happens inside the TreeViewModel's data provider. Data provider cannot be taken outside the cell tree and therefore I need to do all data populating inside the cell tree, which is in the view. Now, the view needs to know about the model and the MVP patter is broken. I wan't to dynamically populate data to the cell tree prior to showing it to user, I need to edit the data in cell tree and save it later for different format.
My question goes how to implement CellTree, or in general Cell widgets, in MVP design patter?
I have used CellTable with MVP.
UI:
<g:HTMLPanel>
<g:ScrollPanel>
<p1:CellTable ui:field="cellTable" width="100%" styleName="style.cellTable" height="100%" />
</g:ScrollPanel>
</g:HTMLPanel>
View Interface:
public interface SomeCellListView extends IsWidget {
void setPresenter(Presenter listener);
// Method to set the CellTable data
void setCellList(ArrayList<ObjectDTO> list);
public interface Presenter {
void goTo(Place place);
void doSomething(int id);
}
}
View Implementation:
public class SomeCellListViewImpl extends Composite implements SomeCellListView {
... all Ui Binder stuff here
#UiField(provided = true)
CellTable<ObjectDTO>cellTable = new CellTable<ObjectDTO>();
SomeCellListViewImpl(){
TextColumn<ObjectDTO> someColumn= new TextColumn<ObjectDTO>(){
#Override
public String getValue(ObjectDTO o) {
return o.getSomeFieldValue();
}
};
cellTable.addColumn(someColumn, "column1");
... add other columns here
}
// This method is called from Presenter to set CellTable data
public void setCellList(ArrayList<ObjectDTO> list) {
cellTable.setRowCount(list.size(), true);
cellTable.setRowData(0, list);
}
}
Activity (or Presenter):
// Set view and service in the constructor (Get the view from ClientFactory)
public void start(AcceptsOneWidget containerWidget, EventBus eventBus) {
// Make RPC call
this.service
.getCellList(new AsyncCallback<ArrayList<ObjectDTO>>(){
#Override
public void onFailure(Throwable caught) {
view.setError("Error fetching details");
}
#Override
public void onSuccess(ArArrayList<ObjectDTO> result) {
view.setCelllist(result);
}
});
view.setPresenter(this);
containerWidget.setWidget(view.asWidget());
}
Here, the view is already created by ClientFactory. View contains just the layout for CellTable. Data is not loaded when view is created. When an Activity is started (aka Presenter), the "start" method is invoked. Here we make the RPC to get Cell data and call a method in the view to set the data.
I've not used CellTree. But you asked in general about Cell widgets. Hence thought of sharing this. Hope this helps.
i have the same issue with OP. I read the MVP tutorial part II, and then try to use CellTable in my application, while still keep the MVP architect. But i confuse at the part: the tutorial use the syntax like Presenter, but why you only use Presenter ?

GWT UiHandler on HTMLPanel

I'm writing a widget with the following markup:
<g:HTMLPanel ui:field="shortcutPanel" styleName="{style.shortcut}">
<g:Image ui:field="shortcutImage"></g:Image>
<span ui:field="shortcutLabel"></span>
</g:HTMLPanel>
So essentially a div that wraps and image and a label. Now, instead of adding the event handlers on the image/span, I'd like an onClick to be associated with the HTMLPanel. My problem however is that gwt tells me that
shortcutPanel doesn't not have an addClickHandler method associated
So I'm assuming the difference is that HTMLPanel doesn't implement HasClickHandlers or something along that line. I'm wondering then what is the standard way to attach a click handler to a Ui element such as an HTMLPanel or even better, is there such a GWT Widget that is essentially a div wrapper that I can easily attach events to with the #UiHandler annotation.
You are probably looking for FocusPanel - it has all the goodies: HasAllFocusHandlers, HasAllKeyHandlers, HasAllMouseHandlers, HasBlurHandlers, HasClickHandlers.... to name a few :) I find it to be the easiest and best way to attach click handlers to a Panel.
I haven't done this before, but you could do the following:
Create a custom class MyPanel that extends HTMLPanel and implements HasClickHandlers
Add the following method in MyPanel.java
public HandlerRegistration addClickHandler(ClickHandler handler) {
return addDomHandler(handler, ClickEvent.getType());
}
Then replace HTMLPanel with MyPanel in your ui.xml and its corresponding Java implementation.
You can always look at the implementation of HTMLTable to get an understanding of how the event propagation works. It's a Panel and implements HasClickHandlers.
If you want to use the #UiHandler annotation to register event handlers for your custom widget, you need to re-implement the addXXHandler methods. The GWT compiler doesn't seem to find those in superclasses. e.g. if you want to use
#UiHandler("myCustomWidget")
public void handleWidgetSelectionChangeEvent(final SelectionEvent<CountryDts> event) {
...
}
and your CustomWidget extends a class for which this is working, you might need to add the HasSelectionHandlers interface explicitly to your class:
public class CustomComboBox<D> extends ComboBox<D> implements HasSelectionHandlers<D> {
#Override
#SuppressWarnings("pmd.UselessOverridingMethod")
public HandlerRegistration addSelectionHandler(final SelectionHandler<D> handler) {
// GWT Compile doesn't recognize method in supertype for UIHandler
return super.addSelectionHandler(handler);
}
...
}