Conditional formats in Grid

I have a datetime column in a database table which results in a column of Timestamps in a Grid. Some items have timestamp data, some are null.

First, I want to format the timestamps for presentation. This does the trick:

        // renders the timestamps in the form YYYY-MM-DD HH:MM
        deferraltimeColumn.setRenderer(new DateRenderer("%1$tY-%1$tm-%1$te %1$tR"));

Well, sort of. Now all the nulls in the table become text: “null-null-null null”. These can be cosmetically fixed by formatting the nulls using transparent text in css.

.v-grid-cell.transparent {
    color: rgba(0, 0, 0, 0.0);
}

That looks fine now, but invisible null text now complicates filtering…

I miss Table’s formatPropertyValue method which worked like a charm for this kind of problem.

As another example, I had previously formatted date/times occuring within today as HH:MM, while times for other days get the longer format of YYYY-M-DD HH:MM. I’m hoping not to have to wrap each container in a GeneratedPropertyContainer as this would need to be repeated for each Grid, and is not well suited to passing fine grained and repetitive formatting tasks off to helper classes.

What’s the best practice for this stuff in a Grid world?

Hi Steve,

The handling (or lack thereof) of null in DateRenderer is a
bug
; null values should be rendered as empty strings. As a workaround, you can do:

setRenderer(new DateRenderer() {
    @Override
    public JsonValue encode(Date value) {
        if(value == null) return encode("", String.class);
        else return super.encode(value);
    }
});

Thanks Johannes, that works perfectly. I’ll keep an eye on #16560.

Similarly, you can also easily either extend DateRenderer or write your own to do more fine-grained customization on how the dates are rendered - you don’t need to modify the client side as dates are formatted on the server and passed to the client as strings.

Yes, extending the DateRenderer is proving to be a good solution for simple customization. It makes a good place to put your workaround too. Thanks.

Then there are Converters too - it’s actually arguable that DateRenderer, not doing anything special with the DOM, shouldn’t really exist and the builtin StringToDateConverter or its subclass be used instead (though currently it has less functionality than DateRenderer…) The separation of concerns between column renderers and converters is not entirely clear.

Johannes, further to your work on #16560, the scope of work should probably extend to all the renderers because Grid cells will frequently be empty. As for what to do with the nulls - empty strings are working for me so far but having some control over the null representation might prove useful.

In the mean time, crude workarounds are growing like this one used only to round to 0 decimal places. Thanks again for your advice - without it, Grid would be unmanageable at this early stage.

    public class TemporaryNoDecimalNumberRenderer extends NumberRenderer {
        private final DecimalFormat noDecimalFormat = new DecimalFormat("#");
        public TemporaryNoDecimalNumberRenderer() { }
        @Override
        public JsonValue encode(Number value) {            
            if ( value != null ) {
                return encode(noDecimalFormat.format(value), String.class);
            } else {
                return encode("", String.class);
            }
        }        
    }

Yes, I reviewed all the Renderers. For those that simply output data, an empty cell is probably the best way to go at least until someone asks for customization. For those that display widgets, it’s a bit more complicated. Probably hiding the widget is also the way to go (instead of rendering eg. a button without a caption).