PDA

View Full Version : [CLOSED] Problem adding data to a Paging Table



Dave_N_Finch
30 Jun 2008, 11:05 PM
Hi,
I am having trouble with adding data to a paging table. i have followed the example in the explorer and data is retrieved and displayed fine. I also have an update page which correctly updates the data in the table using store.update().
The problem comes when adding data using the the store.add() method, this results in columns resizing to about 10-20 pixels wide. clicking on a column heading to sort the data results in the correct sizing being restored.
I am using server side sorting and floats to difine the column widths as percentages.

I am always hesitent to report a 'bug' when the problem may just be a lack of understanding, is there something else i need to do when adding data to a table?

thanks in advance,
Dave

gslender
30 Jun 2008, 11:36 PM
post the code you are using to add/define/setup the table - best if you can post an example standalone app that includes the onModuleLoad so that we can verify any other bits that might be impacting the rendering of the table... the more you can post/verify independantly the easier it is to determine the bug or problem you are having.

Dave_N_Finch
1 Jul 2008, 11:47 AM
Hi,
Here is some of my code. it is not stand alone right now but i can do that tomorrow maybe if needed.

The main list page code:



public abstract class ListLayoutContainer<T extends BaseModel> extends BasicContainer {
private TableBinder<T> binder = null;
private ContentPanel panel = new ContentPanel();
private String serviceName;
private ListStore<T> store;
private PagingLoader loader;

public ListLayoutContainer(String serviceName) {
this.serviceName = serviceName;
}

protected abstract List<TableColumn> getColumns();

protected abstract void initToolbar(ToolBar toolBar);

public List<T> getSelection() {
return binder.getSelection();
}

@SuppressWarnings("unchecked")
@Override
protected void onRender(Element parent, int pos) {
super.onRender(parent, pos);

final ListViewSupport<T> service = (ListViewSupport<T>) Registry.get(serviceName);

if (service == null) {
MessageBox box = new MessageBox();
box.setButtons(MessageBox.OK);
box.setIcon(MessageBox.INFO);
box.setTitle("Information");
box.setMessage("No service detected");
box.show();
return;
}

FlowLayout layout = new FlowLayout();
setLayout(layout);

// create the column model
TableColumnModel cm = new TableColumnModel(getColumns());
Table table = new Table(cm);

RpcProxy proxy = new RpcProxy() {
@Override
public void load(Object loadConfig, AsyncCallback callback) {
service.find((PagingConfig) loadConfig, callback);
}
};

// loader
loader = new PagingLoader(proxy);
loader.setRemoteSort(true);

// store
store = new ListStore<T>(loader);
store.setModelComparer(new EntityComparer<T>());

// binder
binder = new TableBinder<T>(table, store);

final PagingToolBar pagingToolBar = new PagingToolBar(50);
pagingToolBar.bind(loader);

ToolBar toolBar = new ToolBar();
initToolbar(toolBar);

panel.setButtonAlign(HorizontalAlignment.CENTER);
panel.getHeader().setVisible(false);
panel.setLayout(new FitLayout());
panel.add(table);
panel.setWidth("100%");
panel.setHeight("100%");
panel.setBottomComponent(pagingToolBar);
panel.setTopComponent(toolBar);

// load after rendering
DeferredCommand.addCommand(new Command() {
public void execute() {
loader.load(0, 50);
}
});

add(panel);
}

public void update(T model) {
if(store.findModel(model) != null){
store.update(model);
}else{
store.add(model);
}
}

public static class EntityComparer<T extends BaseModel> implements ModelComparer<T> {
public static final String FIELD_ID = "id";

public boolean equals(T m1, T m2) {
if (m1 != null && m2 != null && m1.get(FIELD_ID) != null && m2.get(FIELD_ID) != null) {
return m1.get(FIELD_ID).equals(m2.get(FIELD_ID));
}
return false;
}

}
}



that class is abstract, each list page is similar to:


public class UserListPage extends ListLayoutContainer<User> {

public UserListPage() {
super(Constants.SERVICE_USER);
}

@Override
protected List<TableColumn> getColumns() {
List<TableColumn> columns = new ArrayList<TableColumn>();
columns.add(new TableColumn(User.FIELD_ID, Msg.msg(Msg.FIELD_ID), .10f));
columns.add(new TableColumn(User.FIELD_FIRST_NAME, Msg.msg(Msg.FIELD_FIRST_NAME), .25f));
columns.add(new TableColumn(User.FIELD_LAST_NAME, Msg.msg(Msg.FIELD_LAST_NAME), .25f));
columns.add(new TableColumn(User.FIELD_EMAIL_ADDRESS, Msg.msg(Msg.FIELD_EMAIL_ADDRESS), .40f));
return columns;
}

protected void initToolbar(ToolBar toolBar) {
TextToolItem openButton = new TextToolItem(Msg.msg(Msg.BTN_EDIT_USER), "icon-menu-show");
openButton.addSelectionListener(new SelectionListener<ComponentEvent>() {
public void componentSelected(ComponentEvent ce) {
List<User> list = getSelection();
if (list.size() == 1) {
AppEvent<User> evt = new AppEvent<User>(AppEvents.NAV_USER_DETAIL, list.get(0));
Dispatcher.get().dispatch(evt);
} else {
MessageBox.alert(Msg.msg(Msg.GEN_ALERT), Msg.msg(Msg.ERR_SELECT_ONE_RECORD), null);
}
}
});
toolBar.add(openButton);
TextToolItem addButton = new TextToolItem(Msg.msg(Msg.BTN_ADD_USER), "icon-menu-show");
addButton.addSelectionListener(new SelectionListener<ComponentEvent>() {
public void componentSelected(ComponentEvent ce) {
AppEvent<User> evt = new AppEvent<User>(AppEvents.NAV_USER_DETAIL, new User());
Dispatcher.get().dispatch(evt);
}
});
toolBar.add(addButton);
}

}


as you can see the toolbar has add and edit buttons which both on a detail page:


public class UserDetailsPage extends BasicContainer {

private User user;
private FormBinder<User> formBinder = new FormBinder<User>();
private FormPanel panel = new FormPanel();

public UserDetailsPage(User user) {
this.user = user;
}

@Override
protected void onRender(Element parent, int pos) {
super.onRender(parent, pos);

final UserUIServiceAsync service = (UserUIServiceAsync) Registry.get("UserUIService");

if (service == null) {
MessageBox box = new MessageBox();
box.setButtons(MessageBox.OK);
box.setIcon(MessageBox.INFO);
box.setTitle("Information");
box.setMessage("No service detected");
box.show();
return;
}

FlowLayout layout = new FlowLayout();
setLayout(layout);

panel.setFieldWidth(210);
panel.setLabelWidth(100);
panel.setButtonAlign(HorizontalAlignment.CENTER);
panel.getHeader().setVisible(false);
panel.setWidth("100%");
panel.setHeight("100%");

final TextField<String> firstNameField = new TextField<String>();
firstNameField.setFieldLabel("First Name");
firstNameField.setEmptyText("Enter your first name");
firstNameField.setAllowBlank(false);
firstNameField.setMinLength(4);
firstNameField.setName(User.FIELD_FIRST_NAME);
panel.add(firstNameField);

final TextField<String> lastNameField = new TextField<String>();
lastNameField.setFieldLabel("Last Name");
lastNameField.setEmptyText("Enter your last name");
lastNameField.setAllowBlank(false);
lastNameField.setMinLength(4);
lastNameField.setName(User.FIELD_LAST_NAME);
panel.add(lastNameField);

final TextField<String> emailAddressField = new TextField<String>();
emailAddressField.setFieldLabel("Email");
emailAddressField.setEmptyText("Enter your email address");
emailAddressField.setAllowBlank(false);
emailAddressField.setMinLength(4);
emailAddressField.setName(User.FIELD_EMAIL_ADDRESS);
panel.add(emailAddressField);

ToolBar toolBar = new ToolBar();

TextToolItem saveButton = new TextToolItem("Save User", "icon-user-add");
saveButton.addSelectionListener(new SelectionListener<ComponentEvent>() {
public void componentSelected(ComponentEvent ce) {
if (panel.isValid()) {
user.setFirstName(firstNameField.getValue());
user.setLastName(lastNameField.getValue());
user.setEmailAddress(emailAddressField.getValue());

AsyncCallback<User> callback = new AsyncCallback<User>() {
public void onFailure(Throwable e) {
handleException("Failed to save user.", e);
}

public void onSuccess(User result) {
user = result;
formBinder.loadData(user, panel);
// dispatch event to update table....
AppEvent<User> evt = new AppEvent<User>(AppEvents.UPDATE_LIST, user);
evt.setData(ListPage.KEY, ListPage.USER_LIST_PAGE);
Dispatcher.get().dispatch(evt);

Info.display("Success", "The user has been saved.");
}
};
service.save(user, callback);
} else {
MessageBox.alert("Alert", "Correct validation errors first.", null);
}
}
});

toolBar.add(saveButton);
panel.setTopComponent(toolBar);
add(panel);

}

@Override
protected void afterRender() {
super.afterRender();
formBinder.loadData(user, panel);
}
}


The basic flow is as follows:
user clicks add on the list page, this opens the edit page.
user enters the data and clicks save.
the event handler calls the service and on success and then dispatches the user object to the list page.
the controller invokes the update method on the abstract list page.
if the store does not contain the object then store.add is called otherwise store.update is called.
update works fine. add does add the data but resizes all the columns to about 15 pixels wide.

Thanks for your help.
Dave

Dave_N_Finch
1 Jul 2008, 11:58 AM
OK.
The problem goes away if i used fixed column widths rather than floats/percentages so i guess it is a bug somewhere.
Feel free to point out anything with my code if there is a better way of doing anything.
Dave

darrellmeyer
2 Jul 2008, 7:04 AM
Fixed column widths are preferred and upcoming Grid (1.1) will only support fixed widths. However, Grid will introduce both auto fit and force fit modes.

Dave_N_Finch
3 Jul 2008, 1:06 AM
Hi Darrell,
Thanks for the response. Is there a reason that percentage widths are going to be dropped? I find using pecentages user friendly particularly when resizing.
Will auto fit columns fill 100% of the available space and handle resizing as well as percentages?
Cheers,
Dave

darrellmeyer
3 Jul 2008, 10:07 AM
You will get the same functionality with Grid as Table with percentage values. Auto fill will adjust the size of a single column to "fill" the container, and force fit will adjust the size of all columns to fit the container without having horizontal scrolling.

Dave_N_Finch
3 Jul 2008, 10:35 PM
Cool, thanks.