table + external container

I have made very simple example where user can select category and depending user selection table header and table data will change. There is no any effect to change table header or table data.


import java.util.Arrays;
import java.util.Collection;
import java.util.List;

import com.vaadin.Application;
import com.vaadin.data.Container;
import com.vaadin.data.Property;
import com.vaadin.data.Property.ValueChangeEvent;
import com.vaadin.data.util.IndexedContainer;
import com.vaadin.ui.ListSelect;
import com.vaadin.ui.Table;
import com.vaadin.ui.VerticalLayout;
import com.vaadin.ui.Window;

public class Wikipedia extends Application implements
		Property.ValueChangeListener {

	/**
	 * 
	 */
	private static final long serialVersionUID = -7624611444587283774L;
	private Table table;
	private final Container container = new IndexedContainer();
	private ListSelect categorySelect;

	@Override
	public void init() {
		VerticalLayout rootLayout = new VerticalLayout();
		Window root = new Window("Wikipedia", rootLayout);
		setMainWindow(root);

		List<String> values = Arrays
				.asList(new String[] { "Animals", "Flowers" });
		categorySelect = new ListSelect("Please select a category", values);

		categorySelect.addListener(this);
		categorySelect.setImmediate(true);

		root.addComponent(categorySelect);

		table = new Table();
		table.setWidth("100%");
		table.setPageLength(20);
		table.setImmediate(true);
		table.setSelectable(true);
		table.setContainerDataSource(container);

		root.addComponent(table);
	}

	@Override
	public void valueChange(ValueChangeEvent event) {
		String category = (String) categorySelect.getValue();
		System.out.println("Changing category " + category);

		container.removeAllItems();

		Collection<?> containerPropertyIds = container
				.getContainerPropertyIds();
		for (Object id : containerPropertyIds) {
			container.removeContainerProperty(id);
		}

		if (category.equals("Animals")) {
			container.addContainerProperty("Name", String.class, "");
			container.addContainerProperty("Legs", String.class, "");
			container.addContainerProperty("Wings", String.class, "");

			container.addItem(new Object[] { "Cat", "4", "0" });
			container.addItem(new Object[] { "Bird", "2", "2" });

		} else {
			container.addContainerProperty("Name", String.class, "");
			container.addContainerProperty("Color", String.class, "");
			container.addContainerProperty("Pollination", String.class, "");

			container.addItem(new Object[] { "Rose", "Red", "No" });
			container.addItem(new Object[] { "Iris", "Blue", "Yes" });
		}
	}

}

Hi

I think you have hit bug
#3165
(“Removing container property directly from ContainerDataSource breaks Table”). A workaround is to remove the properties by using the Table.removeProperty method instead of removing them directly from the container. (Table.removeProperty calls container.removeProperty but also updates its internal state). If you have Firebug I think you well see a javascript error when running you example.

Thanks for answer. Workaround resolve problem, but there is still one issue.
Row height is very slow (about 5 pixels) after items added. Also text missing (probably because height is slow).


import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collection;
import java.util.List;

import com.vaadin.Application;
import com.vaadin.data.Container;
import com.vaadin.data.Property;
import com.vaadin.data.Property.ValueChangeEvent;
import com.vaadin.data.util.IndexedContainer;
import com.vaadin.ui.ListSelect;
import com.vaadin.ui.Table;
import com.vaadin.ui.VerticalLayout;
import com.vaadin.ui.Window;

public class Wikipedia extends Application implements
		Property.ValueChangeListener {

	/**
	 * 
	 */
	private static final long serialVersionUID = -7624611444587283774L;
	private Table table;
	private Container container = new IndexedContainer();
	private ListSelect categorySelect;

	@Override
	public void init() {
		VerticalLayout rootLayout = new VerticalLayout();
		Window root = new Window("Wikipedia", rootLayout);
		setMainWindow(root);

		List<String> values = Arrays
				.asList(new String[] { "Animals", "Flowers" });
		categorySelect = new ListSelect("Please select a category", values);

		categorySelect.addListener(this);
		categorySelect.setImmediate(true);

		root.addComponent(categorySelect);

		table = new Table();

		table.setWidth("100%");
		table.setHeight("100%");
		table.setPageLength(20);
		table.setImmediate(true);
		table.setSelectable(true);

		container = table;
		// table.setContainerDataSource(container);

		root.addComponent(table);
	}

	@Override
	public void valueChange(ValueChangeEvent event) {
		String category = (String) categorySelect.getValue();
		System.out.println("Changing category " + category);

		container.removeAllItems();

		Collection<?> containerPropertyIds = container
				.getContainerPropertyIds();
		ArrayList<Object> ids = new ArrayList<Object>();
		for (Object id : containerPropertyIds) {
			ids.add(id);
		}

		for (Object id : ids) {
			container.removeContainerProperty(id);
		}

		if (category.equals("Animals")) {
			container.addContainerProperty("Name", String.class, "");
			container.addContainerProperty("Legs", String.class, "");
			container.addContainerProperty("Wings", String.class, "");

			container.addItem(new Object[] { "Cat", "4", "0" });
			container.addItem(new Object[] { "Bird", "2", "2" });
			container.addItem(new Object[] { "Dog", "2", "2" });

		} else {
			container.addContainerProperty("Name", String.class, "");
			container.addContainerProperty("Color", String.class, "");
			container.addContainerProperty("Pollination", String.class, "");

			container.addItem(new Object[] { "Rose", "Red", "No" });
			container.addItem(new Object[] { "Iris", "Blue", "Yes" });
		}
	}

}

The reason is simple, you are not adding any content to the table. The method you are calling (Item Container.addItem(Object itemId)) uses the parameter as the itemId and returns a new Item for you. You can then set individual properties using the Item. What you probably want to call is Table.addItem(Object cells, Object itemId).