GWT: create a table in auto height mode, without scrollbar

20 10 2011

First of create a simple presenter

package com.biancama.test.gwt.webapp.client.presenter;

import com.biancama.test.gwt.webapp.client.ServiceLocator;
import com.google.gwt.event.shared.HandlerManager;
import com.google.gwt.user.client.ui.HasWidgets;

public class AutoHeightGridPresenter extends AbstractPresenter {

	private final Display display;

	public AutoHeightGridPresenter(ServiceLocator serviceLocator,
			HandlerManager eventBus, final Display display) {
		super(serviceLocator, eventBus);
		this.display = display;
	}

	public interface Display extends TopDisplay {
	}

	@Override
	public void go(HasWidgets container) {
		bind();
		container.clear();
		container.add(display.asWidget());

	}

	private void bind() {
		// TODO Auto-generated method stub

	}

}


The EmployeeDTO is

package com.biancama.test.gwt.webapp.shared.dto;

import java.io.Serializable;
import java.math.BigDecimal;
import java.util.Date;

@SuppressWarnings("serial")
public class EmployeeDTO implements Serializable {
	private String firstName;
	private String lastName;
	private String email;
	private String phoneNumber;
	private Date hireDate;
	private BigDecimal salary;
	private BigDecimal commissionPct;

	public String getFirstName() {
		return firstName;
	}

	public void setFirstName(String firstName) {
		this.firstName = firstName;
	}

	public String getLastName() {
		return lastName;
	}

	public void setLastName(String lastName) {
		this.lastName = lastName;
	}

	public String getEmail() {
		return email;
	}

	public void setEmail(String email) {
		this.email = email;
	}

	public String getPhoneNumber() {
		return phoneNumber;
	}

	public void setPhoneNumber(String phoneNumber) {
		this.phoneNumber = phoneNumber;
	}

	public Date getHireDate() {
		return hireDate;
	}

	public void setHireDate(Date hireDate) {
		this.hireDate = hireDate;
	}

	public BigDecimal getSalary() {
		return salary;
	}

	public void setSalary(BigDecimal salary) {
		this.salary = salary;
	}

	public BigDecimal getCommissionPct() {
		return commissionPct;
	}

	public void setCommissionPct(BigDecimal commissionPct) {
		this.commissionPct = commissionPct;
	}

}

and the relative model marker for ext gwt grid

package com.biancama.test.gwt.webapp.shared.dto;

import com.extjs.gxt.ui.client.data.BeanModelMarker;
import com.extjs.gxt.ui.client.data.BeanModelMarker.BEAN;

@BEAN(com.biancama.test.gwt.webapp.shared.dto.EmployeeDTO.class)
public interface EmployeeDTOBeanModel extends BeanModelMarker {

}

Noe since GXT handles currency as Double let create a simple converter for BigDecimal.

package com.biancama.test.gwt.webapp.client.util;

import java.math.BigDecimal;

import com.extjs.gxt.ui.client.widget.form.NumberPropertyEditor;

public class BigDecimalPropertyEditor extends NumberPropertyEditor {

	public BigDecimalPropertyEditor(Class<?> type) {
		super(type);
	}

	@Override
	public Number convertStringValue(String value) {
		try {
			if (type == BigDecimal.class) {
				return new BigDecimal(value);
			}
		} catch (Exception e) {
			e.printStackTrace();
		}
		return super.convertStringValue(value);
	}

}

and finally the view

package com.biancama.test.gwt.webapp.client.view;

import java.math.BigDecimal;
import java.util.ArrayList;
import java.util.List;

import com.biancama.test.gwt.webapp.client.presenter.AutoHeightGridPresenter;
import com.biancama.test.gwt.webapp.client.util.BigDecimalPropertyEditor;
import com.biancama.test.gwt.webapp.client.util.Resources;
import com.biancama.test.gwt.webapp.shared.dto.EmployeeDTO;
import com.extjs.gxt.ui.client.Style.HorizontalAlignment;
import com.extjs.gxt.ui.client.data.BeanModel;
import com.extjs.gxt.ui.client.data.BeanModelLookup;
import com.extjs.gxt.ui.client.event.ButtonEvent;
import com.extjs.gxt.ui.client.event.ColumnModelEvent;
import com.extjs.gxt.ui.client.event.ComponentEvent;
import com.extjs.gxt.ui.client.event.Events;
import com.extjs.gxt.ui.client.event.Listener;
import com.extjs.gxt.ui.client.event.SelectionListener;
import com.extjs.gxt.ui.client.store.ListStore;
import com.extjs.gxt.ui.client.store.Store;
import com.extjs.gxt.ui.client.store.StoreEvent;
import com.extjs.gxt.ui.client.widget.ContentPanel;
import com.extjs.gxt.ui.client.widget.LayoutContainer;
import com.extjs.gxt.ui.client.widget.button.Button;
import com.extjs.gxt.ui.client.widget.form.DateField;
import com.extjs.gxt.ui.client.widget.form.NumberField;
import com.extjs.gxt.ui.client.widget.form.TextField;
import com.extjs.gxt.ui.client.widget.grid.CellEditor;
import com.extjs.gxt.ui.client.widget.grid.ColumnConfig;
import com.extjs.gxt.ui.client.widget.grid.ColumnModel;
import com.extjs.gxt.ui.client.widget.grid.EditorGrid;
import com.extjs.gxt.ui.client.widget.layout.FitLayout;
import com.extjs.gxt.ui.client.widget.layout.FlowLayout;
import com.extjs.gxt.ui.client.widget.toolbar.ToolBar;
import com.google.gwt.i18n.client.DateTimeFormat;
import com.google.gwt.i18n.client.DateTimeFormat.PredefinedFormat;
import com.google.gwt.i18n.client.NumberFormat;
import com.google.gwt.user.client.Element;
import com.google.gwt.user.client.ui.Composite;
import com.google.gwt.user.client.ui.Widget;

public class AutoHeightGridView extends Composite implements
		AutoHeightGridPresenter.Display {

	private ColumnModel cm;
	private ContentPanel cp;
	private EditorGrid<BeanModel> grid;

	private final LayoutContainer container;

	public AutoHeightGridView() {
		container = new LayoutContainer() {
			@Override
			protected void onRender(Element parent, int index) {
				super.onRender(parent, index);
				initWidget();
			}
		};

		initWidget(container);
		// initWidget();
	}

	protected BeanModel createEmptyEmployee() {
		EmployeeDTO employeeDTO = new EmployeeDTO();
		return BeanModelLookup.get().getFactory(EmployeeDTO.class)
				.createModel(employeeDTO);
	}

	private void doAutoHeight() {
		if (grid.isViewReady()) {
			grid.getView().getScroller()
					.setStyleAttribute("overflowY", "hidden");
			cp.setHeight((grid.getView().getBody().isScrollableX() ? 19 : 0)
					+ grid.el().getFrameWidth("tb")
					+ grid.getView().getHeader().getHeight()
					+ cp.getFrameHeight()
					+ grid.getView().getBody().firstChild().getHeight());
		}

	}

	protected void initWidget() {

		container.setLayout(new FlowLayout(10));
		container.getAriaSupport().setPresentation(true);

		List<ColumnConfig> configs = new ArrayList<ColumnConfig>();

		TextField<String> textFirstName = new TextField<String>();
		textFirstName.setAllowBlank(false);
		ColumnConfig column = new ColumnConfig();
		column.setId("firstName");
		column.setHeader("First Name");
		column.setWidth(200);
		column.setRowHeader(true);
		column.setEditor(new CellEditor(textFirstName));
		configs.add(column);

		TextField<String> textLastName = new TextField<String>();
		textLastName.setAllowBlank(false);
		column = new ColumnConfig();
		column.setId("lastName");
		column.setHeader("Last Name");
		column.setWidth(100);
		column.setRowHeader(true);
		column.setEditor(new CellEditor(textLastName));
		configs.add(column);

		DateField dateField = new DateField();
		dateField.getPropertyEditor().setFormat(
				DateTimeFormat.getFormat("dd/MM/y"));
		column = new ColumnConfig();
		column.setId("hireDate");
		column.setHeader("Hire Date");
		column.setEditor(new CellEditor(dateField));
		column.setDateTimeFormat(DateTimeFormat
				.getFormat(PredefinedFormat.DATE_MEDIUM));
		column.setWidth(100);
		configs.add(column);

		column = new ColumnConfig();
		NumberField salaryField = new NumberField();
		salaryField.setPropertyEditor(new BigDecimalPropertyEditor(
				BigDecimal.class));
		column.setId("salary");
		column.setHeader("Salary");
		column.setWidth(100);
		column.setNumberFormat(NumberFormat.getCurrencyFormat());
		column.setEditor(new CellEditor(salaryField));
		configs.add(column);

		cm = new ColumnModel(configs);

		cp = new ContentPanel();
		cp.setBodyBorder(true);
		cp.setIcon(Resources.ICONS.table());
		cp.setHeading("Basic Grid");
		cp.setButtonAlign(HorizontalAlignment.CENTER);
		cp.setLayout(new FitLayout());
		cp.getHeader().setIconAltText("Grid Icon");
		cp.setSize(600, 300);
		container.add(cp);

		final ListStore<BeanModel> store = new ListStore<BeanModel>();
		grid = new EditorGrid<BeanModel>(store, cm);
		grid.setAutoExpandColumn("firstName");
		grid.setBorders(true);
		cp.add(grid);

		ToolBar toolBar = new ToolBar();
		// Add button
		Button add = new Button("Add Employee");
		add.addSelectionListener(new SelectionListener<ButtonEvent>() {

			@Override
			public void componentSelected(ButtonEvent ce) {

				grid.stopEditing();
				store.insert(createEmptyEmployee(), 0);
				grid.startEditing(0, 0);

			}

		});
		toolBar.add(add);
		// Reset Button
		cp.setTopComponent(toolBar);
		cp.setButtonAlign(HorizontalAlignment.CENTER);
		cp.addButton(new Button("Reset", new SelectionListener<ButtonEvent>() {

			@Override
			public void componentSelected(ButtonEvent ce) {
				store.rejectChanges();
			}
		}));
		// Save Button
		cp.addButton(new Button("Save", new SelectionListener<ButtonEvent>() {

			@Override
			public void componentSelected(ButtonEvent ce) {
				store.commitChanges();
			}
		}));

		container.add(cp);

		grid.addListener(Events.ViewReady, new Listener<ComponentEvent>() {
			@Override
			public void handleEvent(ComponentEvent be) {
				grid.getStore().addListener(Store.Add,
						new Listener<StoreEvent<BeanModel>>() {
							@Override
							public void handleEvent(StoreEvent<BeanModel> be) {
								doAutoHeight();
							}

						});
				doAutoHeight();
			}
		});
		grid.addListener(Events.ColumnResize, new Listener<ComponentEvent>() {
			@Override
			public void handleEvent(ComponentEvent be) {
				doAutoHeight();
			}
		});
		grid.getColumnModel().addListener(Events.HiddenChange,
				new Listener<ColumnModelEvent>() {
					@Override
					public void handleEvent(ColumnModelEvent be) {
						doAutoHeight();
					}
				});
	}

	@Override
	public Widget asWidget() {
		return this;
	}

}

and the result is


Actions

Information

Leave a comment