GWT: Showing a String list in DataGrid - gwt

i got a Presenter that is supposed to present a popup window what contains a DataGrip to show log file entries from a String list. I try to set the appropriate settings, but the number of log file lines that are displayed do not match the String list. I tried to enhance the data assignment, resulting in the Presenter not being shown any more.
Could you please give me a hint what i am doing wrong?
The parts of my presenter related to the DataGrid are:
// Create a list data provider.
final ListDataProvider<String> dataProvider = new ListDataProvider<String>();
public interface MyView extends PopupView, HasUiHandlers<DeviceLogfileUiHandlers> {
DataGrid<String> getDataGrid();
}
#Inject
DeviceLogfilePresenterWidget(final EventBus eventBus, final MyView view) {
super(eventBus, view);
getView().setUiHandlers(this);
}
protected void onBind() {
super.onBind();
// Add the cellList to the dataProvider.
dataProvider.addDataDisplay(getView().getDataGrid());
TextColumn<String> stringColumn = new TextColumn<String>() {
#Override
public String getValue(String s) {
return s;
}
};
getView().getDataGrid().addColumn(stringColumn);
}
#Override
protected void onReveal() {
super.onReveal();
}
public void setDeviceLog(List<String> logEntries) {
getView().getDataGrid().setRowData(0, logEntries);
//These entries make the presenter not show up any more:
dataProvider.addDataDisplay(getView().getDataGrid());
dataProvider.setList(logEntries);
getView().getDataGrid().setRowCount(logEntries.size(), true);
getView().getDataGrid().setVisibleRange(0, logEntries.size());
getView().getDataGrid().setPageSize(logEntries.size());
getView().getDataGrid().redraw();
}

Related

How to create a Dynamic table in GWTP

I am a new GWTP user and I am not sure how to create a table in GWTP. I know how to make one in GWT.
// Create a CellTable.
CellTable<Contact> table = new CellTable<Contact>();
// Create name column.
TextColumn<Contact> nameColumn = new TextColumn<Contact>() {
#Override
public String getValue(Contact contact) {
return contact.name;
}
};
But This doesn't seem to work in GWTP. Can someone please help me with getting the values on a button press in a GWTP program.
I'm aware you asked this question over a week ago but you may still be stuck on it so here goes. You just have to make sure you put the right bits of logic in the Presenter and View respectively.
It's no different from MVP (Model-View-Presenter) without GWTP in principle:
Your Presenter has the job of getting the data to fill the CellTable, and passing it to the View:
public class TablePresenter extends Presenter<TablePresenter.MyView, TablePresenter.MyProxy>
{
public interface MyView extends View
{
void addData(List<Contact> accounts); // pass data to view
}
// proxy and constructor omitted for brevity...
#Override
protected void onReveal()
{
super.onReveal();
// server action to get contacts
dispatchAsync.execute(new GetContacts(), new AsyncCallback<GetContactsResult>()
{
#Override
public void onSuccess(GetContactsResult result)
{
getView().addData(result.getContacts());
}
});
}
}
Your View has the job of initially setting up the CellTable and its Columns, as well as receiving the data from the Presenter. Here I show a TextColumn and a Column using a ButtonCell:
public class TableView extends View implements TablePresenter.MyView
{
#UiField
CellTable<Contact> table;
// use a dataprovider to hold the data
private ListDataProvider<Contact> dataProvider = new ListDataProvider<Contact>();
// COLUMNS
TextColumn<Contact> nameColumn;
Column<Contact, String> buttonColumn;
#Inject
public AccountsView(Binder uiBinder)
{
initWidget(uiBinder.createAndBindUi(this));
initTable();
}
private void initTable()
{
nameColumn = new TextColumn<Contact>()
{
#Override
public String getValue(Contact object)
{
return object.name;
}
};
// now add the column to the table
table.addColumn(nameColumn, "Name");
buttonColumn = new Column<Contact, String>(new ButtonCell())
{
// the text of the button
#Override
public String getValue(Contact object)
{
return "Delete " + object.name;
}
};
// set the button action
deleteColumn.setFieldUpdater(new FieldUpdater<Contact, String>()
{
#Override
public void update(int index, Contact object, String value)
{
// whatever you want to do when you click the button
Window.alert("You pressed " + object.name);
}
});
fileTable.addColumn(deleteColumn);
// link dataprovider to the table
dataProvider.addDataDisplay(table);
}
#Override
public void addData(List<Contact> contacts)
{
// clear the dataProvider's list
dataProvider.getList().clear();
// pass the data into the list
dataProvider.setList(contacts);
}
}
Then in your UiBinder:
<g:HTMLPanel>
<b:CellTable ui:field="table" />
</g:HTMLPanel>

GWT: Adding a SubmitHandler to a Form without putting logic in View

I have a GWTP PresenterWidget and View pair that contains a simple search form.
Currently I am adding the SubmitHandler to the form by calling the getSearchForm() method of my View, which is bad practice as it references the actual class instead of an interface:
public class HeaderPresenter extends PresenterWidget<HeaderPresenter.MyView>
{
public interface MyView extends View
{
void submitForm();
Form getSearchForm();
}
// ...omitted for brevity
#Inject
public HeaderPresenter(EventBus eventBus, DispatchAsync dispatchAsync, MyView view, PlaceManager placeManager)
{
// ...omitted for brevity
}
#Override
protected void onBind()
{
super.onBind();
getView().getSearchForm().addSubmitHandler(new SubmitHandler()
{
#Override
public void onSubmit(SubmitEvent event)
{
// stops the form submission
event.cancel();
// now we can do our stuff
String query = getView().getSearchQuery();
if(query != "") // don't search for a blank string
{
PlaceRequest request = new PlaceRequest.Builder().nameToken(NameTokens.search).with("q", query).build();
placeManager.revealPlace(request);
}
}
});
}
Is there a way to add the SubmitHandler in the HeaderPresenter, or will I have to put that code in the View?
I'd like to keep as much logic in the Presenter as possible.
I found a discussion on this here, and ended up using option 4 as suggested by Thomas Broyer:
https://groups.google.com/forum/#!topic/google-web-toolkit/Fbo-SEDjRa4

GWT's Editor Framework and GWTP

building on this answer, i try to integrate the GWT editors into a popup presenter widget. What is the right way to do that?
My view looks like this:
public class DeviceEditorDialogView extends
PopupViewWithUiHandlers<DeviceEditorDialogUiHandlers> implements
DeviceEditorDialogPresenterWidget.MyView {
interface Binder extends UiBinder<PopupPanel, DeviceEditorDialogView> {
}
public interface Driver extends SimpleBeanEditorDriver<DeviceDto, DeviceEditorDialogView> {
}
#Inject
DeviceEditorDialogView(Binder uiBinder, EventBus eventBus) {
super(eventBus);
initWidget(uiBinder.createAndBindUi(this));
}
#Override
public SimpleBeanEditorDriver<DeviceDto, ?> createEditorDriver() {
Driver driver = GWT.create(Driver.class);
driver.initialize(this);
return driver;
}
}
and my presenter looks like this:
public class DeviceEditorDialogPresenterWidget extends PresenterWidget<DeviceEditorDialogPresenterWidget.MyView> implements
DeviceEditorDialogUiHandlers {
#Inject
DeviceEditorDialogPresenterWidget(EventBus eventBus,
MyView view) {
super(eventBus, view);
getView().setUiHandlers(this);
}
/**
* {#link LocalDialogPresenterWidget}'s PopupView.
*/
public interface MyView extends PopupView, DevicesEditView<DeviceDto>, HasUiHandlers<DeviceEditorDialogUiHandlers> {
}
private DeviceDto currentDeviceDTO = null;
private SimpleBeanEditorDriver<DeviceDto, ?> driver;
public DeviceDto getCurrentDeviceDTO() {
return currentDeviceDTO;
}
public void setCurrentDeviceDTO(DeviceDto currentDeviceDTO) {
this.currentDeviceDTO = currentDeviceDTO;
}
#Override
protected void onBind() {
super.onBind();
driver = getView().createEditorDriver();
}
//UiHandler Method: Person person = driver.flush();
}
Is this the right approach? What is missing? Currently nothing happens when i try to use it like this:
#Override
public void showDeviceDialog() {
deviceEditorDialog.setCurrentDeviceDTO(new DeviceDto());
addToPopupSlot(deviceEditorDialog);
}
showDeviceDialog is in the parent presenter and called when clicking a button in that parent Presenter, that instantiates the dialog with private final DeviceEditorDialogPresenterWidget deviceEditorDialog;
Thanks!
Here are a few key points that are missing from your code above:
Your DeviceEditorDialogView should implement Editor<DeviceDto>. This is required in order for the fields of DeviceEditorDialogView to be populated with data from you POJO.
Your DeviceEditorDialogView should have child editors that are mapped to fields in your POJO. For example, given the field deviceDto.modelName (type String), you could have a GWT Label named modelName in your DeviceEditorDialogView. This Label implements Editor<String> and will be populated with the modelName from your DeviceDto when you call driver.edit(deviceDto)
You should call driver.initialize(this) only once, in DeviceEditorDialogView's constructor
You should override onReveal() like this:
#Override
public void onReveal() {
super.onReveal();
driver.edit(currentDeviceDTO); // this will populate your view with the data from your POJO
}
This method will be called when the popup is displayed, just after your DeviceEditorDialogPresenterWidget has been addToPopupSlot

Editor not getting ListBox changes

Issue: On load of a form, ParentEditor, a sub-editor, ThisEditor, properly
popluates all its fields including a listbox(dropdown) widget, MyWidget. However,if I select a new option in the listbox and save, it doesn't save the newly selected option; though edits to other widgets are saving fine. It appears that on a driver flush, the editor does not get the value in my listBox. In debug mode, on driver.edit, I can see the TakesValueEditor call setValue(value) on all form widgets including the listbox. But on flush, I can see the TakesValueEditor call its getValue() on other form widgets but
not on my listbox.
The editor hierarchy: ParentEditor > ThisEditor > MyWidget. ParentEditor is the entire form. ThisEditor is a sub-section of the form. MyWidget is a custom listbox in ThisEditor section.
I'm using MVP pattern. Below are sample code snippets of the View and Presenter:
VIEW:
/** ThisEditor is a sub-section of ParentEditor (the Form) and contains a
MyWidget (custom listbox). */
public class ThisEditor extends Composite implements Editor<ThisProxy>, ThisView {
... //rfeDriver interface defined and created here
#UiField
MyWidget my; //getMy and setMy methods in ThisProxy
... //other field declarations
public ThisEditor() {
initWidget(binder.createAndBindUi(this));
}
#Override
public MyView getMy() {
return my;
}
... //other methods
}
/** This is the View interface that MyWidget implements */
public interface MyView extends HasOptions, HasValue<MyProxy>, Focusable {
interface Presenter {
...
}
...
}
public class MyWidget extends Composite implements MyView,
IsEditor<LeafValueEditor<MyProxy>> {
...
#UiField
ListBox listBox; //single-select dropdown
...
public MyWidget() {
initWidget(binder.createAndBindUi(this));
addChangeHandler(); //listen to changes to listBox and setSelectedIndex (?)
}
...
#Override
public int getSelectedIndex() {
return listBox.getSelectedIndex();
}
#Override
public void setSelectedIndex(int index) {
listBox.setSelectedIndex(index);
}
...
/**
* Called by the TakesValueEditor on rfeDriver.edit.
*/
#Override
public MyProxy getValue() {
//ask presenter for the MyProxy object -- presenter calls
//getSelectedIndex() on this widget and returns the object associated
//with the index
return presenter.getValue();
}
/**
* Called by the TakesValueEditor on rfeDriver.flush.
*/
#Override
public void setValue(MyProxy value) {
//pass the value to the presenter to parse and set the index that corresponds
//to this object
presenter.setValue(value);
}
PRESENTER
public class MyPresenter implements MyView.Presenter,
ValueLookupCompleteEventHandler {
...
protected HasOptions view;
private List<MyProxy> myList;
public MyPresenter(ParentPresenter parent) {
//setParent for this child presenter
}
... //methods to set view and create association between view and presenter
#Override
public MyProxy getValue() {
//identify the current selection
String selectedId = view.getValue(view.getSelectedIndex());
if (selectedId != null) {
//iterate myList to find the MyProxy object whose id.equals(selectedId)
for (Iterator<MyProxy> i = myList.iterator(); i.hasNext();) {
MyProxy value = i.next();
if (selectedId.equals(value.getCode().toString())) {
return value;
}
}
}
return null;
}
#Override
public void setValue(MyProxy value) {
//handle null value
String selectedId = value.getCode().toString();
... //verify the value is in myList
//traverse dropdown list and set selected index corresponding to value object
for (int i = 0; i < view.getItemCount(); ++i) {
if (selectedId.equals(view.getValue(i))) {
view.setSelectedIndex(i);
}
}
}
}
I just ran into this same issue. If you look at the source code for the GWT ListBox, you'll se e that it does not implement isEditor. I actually don't think it is a GWT editor component. Hard to understand. I had to code around it.

GWT 2.1 Places example without Activities

does anyone have any examples of how to using Places without using activities for history management. I knocked something up quickly and can see the url changing with browser-back and browser-forward clicks but the display doesn't go anywhere.
I'm using a DecoratedTabPanel and have a SelectionHandler that fires off getPlaceController().goTo(place).
Any ideas would be useful.
Here is a simple piece of code that I've made to demonstrate what you expected. It's based on the GWT and MVP Development document (GWT and MVP)
In this example you navigate between two tabs. On selection, a new history item is created (without any activity). As long as you use browser buttons to go back/forward the page will be updated correctly.
I have defined one place, one activity and its view. I've adjusted AppActivityMapper, AppActivityManager and ClientFactory to my needs. The code is lightweight and doesn't need comments to be understood. I've only put some explanations when it was needed, but if it's not clear do not hesitate to ask.
ExampleView.java
public interface ExampleView extends IsWidget {
void selectTab(int index);
}
ExampleViewImpl.java
public class ExampleViewImpl extends Composite implements ExampleView, SelectionHandler<Integer> {
private DecoratedTabPanel panel;
public ExampleViewImpl() {
panel = new DecoratedTabPanel();
initComposite();
initWidget(panel);
}
private void initComposite() {
panel.add(new HTML("Content 1"), "Tab 1");
panel.add(new HTML("Content 2"), "Tab 2");
panel.selectTab(0);
panel.addSelectionHandler(this);
}
#Override
public void selectTab(int index) {
if (index >=0 && index < panel.getWidgetCount()) {
if (index != panel.getTabBar().getSelectedTab()) {
panel.selectTab(index);
}
}
}
#Override
public void onSelection(SelectionEvent<Integer> event) {
// Fire an history event corresponding to the tab selected
switch (event.getSelectedItem()) {
case 0:
History.newItem("thetabplace:1");
break;
case 1:
History.newItem("thetabplace:2");
break;
}
}
}
ClientFactory.java
public class ClientFactory {
private final EventBus eventBus = new SimpleEventBus();
private final PlaceController placeController = new PlaceController(eventBus);
private final ExampleViewImpl example = new ExampleViewImpl();
public EventBus getEventBus() {
return this.eventBus;
}
public PlaceController getPlaceController() {
return this.placeController;
}
public ExampleViewImpl getExampleView() {
return example;
}
}
ExampleActivity.java
public class ExampleActivity extends AbstractActivity {
private ExampleView view;
private ClientFactory factory;
public ExampleActivity(ExamplePlace place, ClientFactory factory) {
// Get the factory reference
this.factory = factory;
// Get the reference to the view
view = this.factory.getExampleView();
// Select the tab corresponding to the token value
if (place.getToken() != null) {
// By default the first tab is selected
if (place.getToken().equals("") || place.getToken().equals("1")) {
view.selectTab(0);
} else if (place.getToken().equals("2")) {
view.selectTab(1);
}
}
}
#Override
public void start(AcceptsOneWidget panel, EventBus eventBus) {
// Attach this view to the application container
panel.setWidget(view);
}
}
ExamplePlace.java
/**
* Just an very basic place
*/
public class ExamplePlace extends Place {
// The token corresponding to an action
private String token;
// This place should use a token to identify a view behavior
public ExamplePlace(String token) {
this.token = token;
}
// Return the current token
public String getToken() {
return token;
}
// Custom prefix to break the default name : ExamplePlace
// So that the history token will be thetabplace:token
// and not any more : ExamplePlace:token
#Prefix(value="thetabplace")
public static class Tokenizer implements PlaceTokenizer<ExamplePlace> {
#Override
public String getToken(ExamplePlace place) {
return place.getToken();
}
#Override
public ExamplePlace getPlace(String token) {
return new ExamplePlace(token);
}
}
}
AppActivityMapper.java
public class AppActivityMapper implements ActivityMapper {
private ClientFactory clientFactory;
public AppActivityMapper(ClientFactory clientFactory) {
super();
this.clientFactory = clientFactory;
}
#Override
public Activity getActivity(Place place) {
if (place instanceof ExamplePlace) {
return new ExampleActivity((ExamplePlace) place, clientFactory);
}
return null;
}
}
AppPlaceHistoryMapper.java
#WithTokenizers({ExamplePlace.Tokenizer.class})
public interface AppPlaceHistoryMapper extends PlaceHistoryMapper
{
}
All together
private Place defaultPlace = new ExamplePlace("1");
private SimplePanel appWidget = new SimplePanel();
public void onModuleLoad() {
ClientFactory clientFactory = new ClientFactory();
EventBus eventBus = clientFactory.getEventBus();
PlaceController placeController = clientFactory.getPlaceController();
// Start ActivityManager for the main widget with our ActivityMapper
ActivityMapper activityMapper = new AppActivityMapper(clientFactory);
ActivityManager activityManager = new ActivityManager(activityMapper, eventBus);
activityManager.setDisplay(appWidget);
// Start PlaceHistoryHandler with our PlaceHistoryMapper
AppPlaceHistoryMapper historyMapper= GWT.create(AppPlaceHistoryMapper.class);
PlaceHistoryHandler historyHandler = new PlaceHistoryHandler(historyMapper);
historyHandler.register(placeController, eventBus, defaultPlace);
RootPanel.get().add(appWidget);
// Goes to the place represented on URL else default place
historyHandler.handleCurrentHistory();
}