Table.addGeneratedColumn() and sorting

Hi,

I am using this to format a date in a table:

table.addGeneratedColumn(“date”,new DateColumnGenerator());

How can I make sure that the sort function of the table columns works correctly, even if the date format is not 2011-12-24, but 24.12.2011?

Thanks,
Roland

Hi,

This seems to be a common problem. See
this forum article
for tips on how to work around the problem.

Hi,

In short - you can’t. It’s not possible to sort on a generated column.

However, there is a much better way of formatting your column - override Table#formatPropertyValue; see section
5.14.6 in the Book Of Vaadin

As an aside, I would only ever use a generated column if I didn’t want a textual value for the column.

Cheers,

Charles.

While formatting as suggested by Charles might be better here, you can make a generated column sortable (based on the underlying data or a separate ItemSorter) if it “shadows” a real column in the container with the same property id.

Hi Henri,
We tried the following code for sorting on column for table generated column , but does not work.

getTableRating().addHeaderClickListener(new HeaderClickListener() {
private static final long serialVersionUID = 1L;

                 @Override
                 public void headerClick(HeaderClickEvent event) {
                       //Notification.show(event.getButtonName() +"   " + event.getPropertyId().toString(), Type.ERROR_MESSAGE);
                       boolean [] ordering={true};
                       Object [] properties={event.getPropertyId().toString()};
                       tableDataContainer.sort(properties, ordering);

// getTableRating().sort(properties,ordering);
getTableRating().refreshRowCache();
}
});

Thanks
Shakir

In your case, the generated column replaces one with the same ID in the underlying container so you should not try to hack this with a header click listener etc.

Instead, just make the real data column sortable (data type of the column should implement Comparable, or override container.getSortableContainerPropertyIds() if that is not doable) and, if needed, write and set a suitable ItemSorter for the container to customize the sort order. Usually table.setSortEnabled(true) is not needed as it is true by default.

As an aside, the code calling getTableRating().refreshRowCache() after container.sort(…) is useless. It can even be harmful here (performance-wise) as if the sort() works, it already notifies the table and then the refreshRowCache() may force the table to perform additional unnecessary operations.

In general, refreshRowCache() should be avoided when not absolutely necessary - it is not needed when performing modifications correctly through Vaadin data APIs.

Please, note that in Vaadin 7, you can use Table DateFormatters or the Converters.

I use converters for example, to translate ENUM Values on table. Bellow a example of the enum converter implementation. You can use something like that for Date too:


package br.com.autmix.web.gui.components.converters;

import java.util.Locale;

import com.vaadin.data.util.converter.Converter;

import br.com.autmix.shared.spi.i18n.I18NService;
import br.com.autmix.web.gui.context.ServiceFactory;
import br.com.autmix.web.gui.session.Session;

@SuppressWarnings("rawtypes")
public class EnumToStringConverter implements Converter<String, Enum> {

	private static final long serialVersionUID = 1L;
	
	private I18NService i18nService = ServiceFactory.instance().getI18nService();

	@Override
	public String convertToPresentation(Enum value, Class<? extends String> targetType, Locale locale)
			throws com.vaadin.data.util.converter.Converter.ConversionException {
		return value == null ? null : translate(value.getClass(), value.name());
	}

	@Override
	public Class<Enum> getModelType() {
		return Enum.class;
	}
	
	@Override
	public Class<String> getPresentationType() {
		return String.class;
	}

	@Override
	public Enum convertToModel(String value, Class<? extends Enum> targetType, Locale locale)
			throws com.vaadin.data.util.converter.Converter.ConversionException {
		if(value == null) {
			return null;
		} else {
			for(Enum e : targetType.getEnumConstants()) {
				String translated = translate(targetType, e.name());
				if(value.equals(translated)) {
					return e;
				}
			}
			return null;
		}
	}
	
	private String translate(Class<?> targetType, String id) {
		String grupo = targetType.getName();
		return i18nService.getMensagem(grupo, Session.userInfo().getLingua(), id);
	}

}

You can apply the converter directly to the widget instance, of, as a Default Converger for that type, like:


VaadinSession.getCurrent().setConverterFactory(new CustomConverterFactory());

So, you will dont need generated columns only to print presentation values of your model.

Hello :slight_smile:

I’m using Vaadin 6 and I am facing the exact same problem. I used Henri’s approach with using an alias but I am not really sure if I understand how it should work. When I use a propertyId that actually exists in a container the table is sorted based on that property and not the column I want. I assume I should override or implement some method but I don’t know which one (I am using JPAContainer which is quite problematic).

The sorting needs to be done in the database as the datasets can be big.

JPAContainer delegates sorting to the EntityProvider, giving it a List to tell based on what to sort. Thus, to customize the sort, you would need to override a number of EntityProvider methods. Some entity providers (e.g. CachingLocalEntityProvider) delegate logic to CachingSupport, which delegates more to a LocalEntityProvider. LocalEntityProvider.translateSortBy() is probably the method to customize, but getting to override it for the instance used might be a bit tricky if you use caching.

Hello @Charles,

I am using table.addGeneratedColumn("id",new TextGeneratedColumn(1)); Where, TextGeneratedColumn is implementation of ColumnGenerator.

for adding data to my table, and as other even I face the same issue of not be able to sort data after click on column header. Can you please tell me if its still exist ? I am using Vaading 7.3.x.
When I use Object array to add data into column, then sorting is working properly but not with addGeneratedColumn. Is there any way to enable it ?

Hi All ,

I have a table with a generated column ComboBox using dataSource as a BeanItem Container with some custom object and setDatasource to that combobox and as well as one Textfield added as another column. Now the requirement is to sort the columns so i approach as default item sort for bean item container with creating the comparator class and i able to do sort for TextField because it is String type Column but unable to do for ComboBox column it has a different object.

Please help me on this how can i able to do sort the column using ComboBox component.

Please i added some piece of snippet code
BeanItemContainer cont = loadContainer.getContainer();
cont.setItemSorter(new DefaultItemSorter(new SortIgnoreCase()));
cont.sort(new Object { “col1” }, new boolean
{ true });
setContainerDataSource(cont);

class SortIgnoreCase implements Comparator<Object> {

    public int compare(Object o1, Object o2) {

        if (o1 instanceof String && o2 instanceof String) {
            String s1 = (String) o1;
            String s2 = (String) o2;
            System.out.println("****" + s1 + "," + s2);
            return s1.toLowerCase().compareTo(s2.toLowerCase());
        } else{

        }

        return 0;
    }
}