Book of Vaadin Examples – Item Editor From Bugfix

Hi all,
I try to
use the example
of the “ Item Editor Form”. If i clicked on “New Bean”, the table was disabled, but no form field are visible

Screenshot


After debugging I’m found a bit of bugs in java source code.:
If a new Bean will be added to BeanItemContainer the BeanItem will be used as item Id.

public void buttonClick(ClickEvent event) {
			// Create a new item; this will create a new bean
Object itemId = beans.addItem(new Bean("Foo", 42.0));

But it is
not correct
. The entire Bean must be used as Id. Otherwise the
null
would be returned if either
beans.getItem(id)
or
table.getItem(itemId
) would be call.
That is the correct fragment…

BeanItem beanItem = beans.addBean(new Bean("Foo", 42.0
Object itemId=beanItem == null ? null: beanItem.getBean();

The application to test:

package com.example;

import com.vaadin.Application;
import com.vaadin.ui.Window;


public class TableEditWithFormExampleApplication extends Application {

	/**
	 * 
	 */
	private static final long serialVersionUID = 3041673750186742950L;

	@Override
	public void init() {
		Window mainWindow = new Window();
		setMainWindow(mainWindow);
		TableEditWithFormExample c = new TableEditWithFormExample();
		c.init();
		mainWindow.addComponent(c);
	}

}


The example code

package com.example;

import java.io.Serializable;
import com.vaadin.data.Item;
import com.vaadin.data.Property;
import com.vaadin.data.Property.ValueChangeEvent;
import com.vaadin.data.Property.ValueChangeListener;
import com.vaadin.data.util.BeanItem;
import com.vaadin.data.util.BeanItemContainer;
import com.vaadin.event.FieldEvents.TextChangeEvent;
import com.vaadin.event.FieldEvents.TextChangeListener;
import com.vaadin.ui.AbstractField;
import com.vaadin.ui.Button;
import com.vaadin.ui.Button.ClickEvent;
import com.vaadin.ui.Component;
import com.vaadin.ui.CustomComponent;
import com.vaadin.ui.DefaultFieldFactory;
import com.vaadin.ui.Field;
import com.vaadin.ui.Form;
import com.vaadin.ui.HorizontalLayout;
import com.vaadin.ui.Table;
import com.vaadin.ui.TextField;
import com.vaadin.ui.VerticalLayout;

public class TableEditWithFormExample extends CustomComponent {

	private final class CancelListener implements Button.ClickListener {
		private final Table table;

		private final Button newBeanBtn;

		private final Form form;

		private final BeanItemContainer<Bean> beans;

		private static final long serialVersionUID = -1749148888766063606L;

		private CancelListener(Table table, Button newBeanBtn, Form form, BeanItemContainer<Bean> beans) {
			this.table = table;
			this.newBeanBtn = newBeanBtn;
			this.form = form;
			this.beans = beans;
		}

		public void buttonClick(ClickEvent event) {
			form.discard(); // Not really necessary
			form.setVisible(false); // and close it
			table.discard(); // Discards possible addItem()
			table.setEnabled(true);
			if (table.getData() != null)
				beans.removeItem(table.getData());
			newBeanBtn.setEnabled(true);
		}
	}

	private final class MyFormFieldFactory extends DefaultFieldFactory {
		private final Form form;

		private final Button submitBtn;

		private static final long serialVersionUID = -1844463910858883298L;

		private MyFormFieldFactory(Form form, Button submitBtn) {
			this.form = form;
			this.submitBtn = submitBtn;
		}

		@Override
		public Field createField(Item item, Object propertyId, Component uiContext) {
			final AbstractField field = (AbstractField) super.createField(item, propertyId, uiContext);
			field.addListener(new ValueChangeListener() {
				private static final long serialVersionUID = 5216192896151241766L;

				public void valueChange(ValueChangeEvent event) {
					submitBtn.setEnabled(form.isModified());

				}

			});
			if (field instanceof TextField) {
				final TextField tf = (TextField) field;
				tf.addListener(new TextChangeListener() {
					private static final long serialVersionUID = 5674948434239591166L;

					public void textChange(TextChangeEvent event) {
						if (form.isModified() || !event.getText().equals(tf.getValue())) {
							submitBtn.setEnabled(true);

							// Not needed after first event unless
							// want to detect also changes back to
							// unmodified value.
							tf.removeListener(this);

							// Has to be reset because the
							// removeListener() setting causes
							// updating the field value from the
							// server-side.
							tf.setValue(event.getText());
						}
					}
				});
			}
			field.setImmediate(true);

			return field;
		}
	}

	private final class SubmitListener implements Button.ClickListener {
		private final Button newBeanBtn;

		private final Form form;

		private final Table table;

		private static final long serialVersionUID = 6823630748713272361L;

		private SubmitListener(Button newBeanBtn, Form form, Table table) {
			this.newBeanBtn = newBeanBtn;
			this.form = form;
			this.table = table;
		}

		public void buttonClick(ClickEvent event) {
			form.commit();
			form.setVisible(false); // and close it

			// New items have to be added to the container
//			if (table.getValue() == null) {
				// Commit the addition
				table.commit();

				table.setEnabled(true);
				newBeanBtn.setEnabled(true);
//			}
		}
	}

	private final class NewBeanListener implements Button.ClickListener {
		private final Table table;

		private final Form form;

		private final Button newBeanBtn;

		private final BeanItemContainer<Bean> beans;

		private static final long serialVersionUID = -7340189561756261036L;

		private NewBeanListener(Table table, Form form, Button newBeanBtn, BeanItemContainer<Bean> beans) {
			this.table = table;
			this.form = form;
			this.newBeanBtn = newBeanBtn;
			this.beans = beans;
		}

		public void buttonClick(ClickEvent event) {
			// Create a new item; this will create a new bean
			BeanItem beanItem = beans.addBean(new Bean("Foo", 42.0));//	Object itemId = beans.addItem(new Bean("Foo", 42.0));
			Object itemId=beanItem == null ? null: beanItem.getBean();
			System.out.println("beanItem of the added bean is " + beanItem);
			Object tst = beans.getItem(itemId);
			for (Object id : beans.getItemIds()) {
				System.out.println("current id is " + id);
				System.out.println("current bean is " + beans.getItem(id));
			}
			form.setItemDataSource(table.getItem(itemId));

			// Make the form a bit nicer
			form.setVisibleItemProperties(new Object[] { "name", "energy" });
			//((TextField)form.getField("name"))
			//        .setNullRepresentation("");

			// The form was opened for editing a new item
			table.setData(itemId);

			table.select(itemId);
			table.setEnabled(false);
			newBeanBtn.setEnabled(false);
			form.setVisible(true);
		}
	}

	private final class TableChangeListener implements Property.ValueChangeListener {
		private final Table table;

		private final Form form;

		private static final long serialVersionUID = 1162945655606583495L;

		private TableChangeListener(Table table, Form form) {
			this.table = table;
			this.form = form;
		}

		public void valueChange(ValueChangeEvent event) {
			// Close the form if the item is deselected
			if (event.getProperty().getValue() == null) {
				form.setVisible(false);
				return;
			}

			// Bind the form to the selected item
			form.setItemDataSource(table.getItem(table.getValue()));
			form.setVisible(true);

			// The form was opened for editing an existing item
			table.setData(null);
		}
	}

	// BEGIN-EXAMPLE: component.table.binding.editorform
	public class Bean implements Serializable {
		private static final long serialVersionUID = -1520923107014804137L;

		String name;

		double energy; // Energy content in kJ/100g

		public Bean(String name, double energy) {
			this.name = name;
			this.energy = energy;
		}

		public String getName() {
			return name;
		}

		public void setName(String name) {
			this.name = name;
		}

		public double getEnergy() {
			return energy;
		}

		public void setEnergy(double energy) {
			this.energy = energy;
		}
	}

	public TableEditWithFormExample() {
		// TODO Auto-generated constructor stub
	}

	public void init() {
		VerticalLayout layout = new VerticalLayout();
		editorform();
		if (getCompositionRoot() == null)
			setCompositionRoot(layout);
	}

	private void editorform() {
		VerticalLayout vlayout = new VerticalLayout();

		// Create a container for such beans
		BeanItemContainer<Bean> beans = new BeanItemContainer<Bean>(Bean.class);

		// Add some beans to it
		beans.addBean(new Bean("Mung bean", 1452.0));
		beans.addBean(new Bean("Chickpea", 686.0));
		beans.addBean(new Bean("Lentil", 1477.0));
		beans.addBean(new Bean("Common bean", 129.0));
		beans.addBean(new Bean("Soybean", 1866.0));
		beans.addItem(new Bean("Java Bean", 0.0));
		
		// A layout for the table and form
		HorizontalLayout layout = new HorizontalLayout();

		// Bind a table to it
		final Table table = new Table("Beans of All Sorts", beans);
		table.setVisibleColumns(new Object[] { "name", "energy" });
		table.setPageLength(7);
		table.setWriteThrough(true);
		layout.addComponent(table);

		// Create a form for editing a selected or new item.
		// It is invisible until actually used.
		Form form = new Form();
		form.setCaption("Edit Item");
		form.setVisible(false);
		form.setWriteThrough(false); // Enable buffering
		layout.addComponent(form);

		// When the user selects an item, show it in the form
		table.addListener(new TableChangeListener(table, form));
		table.setSelectable(true);
		table.setImmediate(true);

		// Creates a new bean for editing in the form before adding
		// it to the table. Adding is handled after committing
		// the form.
		Button newBeanBtn = new Button("New Bean");
		newBeanBtn.addListener(new NewBeanListener(table, form, newBeanBtn, beans));

		// When OK button is clicked, commit the form to the bean
		Button submitBtn = new Button("Save");
		submitBtn.addListener(new SubmitListener(newBeanBtn, form, table));
		form.getFooter().addComponent(submitBtn);

		// Make modification to enable/disable the Save button
		form.setFormFieldFactory(new MyFormFieldFactory(form, submitBtn));

		Button cancelBtn = new Button("Cancel");
		cancelBtn.addListener(new CancelListener(table, newBeanBtn, form, beans));
		form.getFooter().addComponent(cancelBtn);
		// END-EXAMPLE: component.table.binding.editorform

		layout.setSpacing(true);
		vlayout.addComponent(layout);
		vlayout.addComponent(newBeanBtn);
		setCompositionRoot(vlayout);
	}

}


web.xml

<?xml version="1.0" encoding="UTF-8"?>
<web-app id="WebApp_ID" version="2.4"
	xmlns="http://java.sun.com/xml/ns/j2ee" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
	xsi:schemaLocation="http://java.sun.com/xml/ns/j2ee http://java.sun.com/xml/ns/j2ee/web-app_2_4.xsd">
	<display-name>TestVaadionVisualDesigner</display-name>
	<context-param>
		<description>
		Vaadin production mode</description>
		<param-name>productionMode</param-name>
		<param-value>false</param-value>
	</context-param>


	<servlet>
		<servlet-name>TableEditWithFormExampleApplication</servlet-name>
		<servlet-class>com.vaadin.terminal.gwt.server.ApplicationServlet</servlet-class>
		<init-param>
			<description>
			TableEditWithFormExampleApplication</description>
			<param-name>application</param-name>
			<param-value>com.example.TableEditWithFormExampleApplication</param-value>
		</init-param>
	</servlet>


	<servlet-mapping>
		<servlet-name>TableEditWithFormExampleApplication</servlet-name>
		<url-pattern>/tbledstwf/*</url-pattern>
	</servlet-mapping>

	<servlet-mapping>
		<servlet-name>TableEditWithFormExampleApplication</servlet-name>
		<url-pattern>/VAADIN/*</url-pattern>
	</servlet-mapping>

	<welcome-file-list>
		<welcome-file>index.html</welcome-file>
		<welcome-file>index.htm</welcome-file>
		<welcome-file>index.jsp</welcome-file>
		<welcome-file>default.html</welcome-file>
		<welcome-file>default.htm</welcome-file>
		<welcome-file>default.jsp</welcome-file>
	</welcome-file-list>
</web-app>