example beanitemcontainer datagrid vaadin renderer vaadin8

datagrid - beanitemcontainer - Implementar un procesador de columnas para Vaadin 8 Grid



vaadin web (1)

La guía de Vaadin Framework tiene una página que describe cómo usar Column Renderers en una Vaadin Grid . Y esta página describe la implementación de renderizadores , pero muy brevemente.

Deseo implementar un InstantRenderer para complementar el conjunto parcial de renderizadores java.time agregados en Vaadin 8.1. Se agregaron LocalDate para LocalDate y LocalDateTime pero no para Instant , OffsetDateTime y ZonedDateTime . Para mi renderizador Instant , actualmente solo estoy aplicando la zona horaria predeterminada actual ( ZoneId ) para obtener un ZonedDateTime al que llamo el método toString . Se podría hacer más, pero esto es solo para comenzar.

Por lo tanto, mi código debería ser muy similar al proporcionado LocalDateTimeRenderer . Estoy tratando de seguir ese código como una guía.

Al buscar el código fuente de Vaadin y leer el documento, parece que necesito tres piezas de código fuente:

He hecho esto, y todo compila. Pero mi tabla no se puede mostrar, todo lo que obtengo es un cuadro vacío en blanco en la página. No aparecen errores en la consola o los registros. Si InstantRenderer mi uso de InstantRenderer y vuelvo a dejar que mis objetos Instant se procesen de manera predeterminada con sus propios métodos toString , todo está bien y la tabla aparece como se esperaba. Así que sé que mi renderizador personalizado tiene la culpa.

Soy un novato cuando se trata de Vaadin "del lado del servidor" frente al "lado del cliente".

➠ ¿Hay algún tipo de empaque que deba realizar? Actualmente tengo mis tres clases en mi proyecto Vaadin junto con el archivo fuente MyUI .

➠ ¿Me falta alguna otra pieza?

Instalo mi representador llamando al constructor no-arg:

this.entriesGrid .addColumn( Entry::getStart ) .setCaption( "Start" ) .setRenderer( new InstantRenderer( ) ) ;

Estos son mis tres archivos enumerados anteriormente, tomados casi por completo del código fuente de Vaadin.

InstantRenderer

/* * By Basil Bourque. Taken almost entirely from source code published by Vaadin Ltd. * * -------- * * Copyright 2000-2016 Vaadin Ltd. * * Licensed under the Apache License, Version 2.0 (the "License"); you may not * use this file except in compliance with the License. You may obtain a copy of * the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the * License for the specific language governing permissions and limitations under * the License. */ package com.basil.timepiece; import java.time.Instant; import java.time.ZoneId; import java.time.ZonedDateTime; import java.time.format.DateTimeFormatter; import java.time.format.FormatStyle; import java.util.Locale; import elemental.json.JsonValue; /** * A renderer for presenting {@code Instant} objects. * * @author Vaadin Ltd * @since 8.1 */ public class InstantRenderer extends com.vaadin.ui.renderers.AbstractRenderer< Object, Instant > { private DateTimeFormatter formatter; private boolean getLocaleFromGrid; private ZoneId zoneId = ZoneId.systemDefault(); // Basil Bourque. /** * Creates a new InstantRenderer. * <p> * The renderer is configured to render with the grid''s locale it is * attached to, with the format style being {@code FormatStyle.LONG} for the * date and {@code FormatStyle.SHORT} for time, with an empty string as its * null representation. * * @see <a href= * "https://docs.oracle.com/javase/8/docs/api/java/time/format/FormatStyle.html#LONG"> * FormatStyle.LONG</a> * @see <a href= * "https://docs.oracle.com/javase/8/docs/api/java/time/format/FormatStyle.html#SHORT"> * FormatStyle.SHORT</a> */ public InstantRenderer () { this( DateTimeFormatter.ofLocalizedDateTime( FormatStyle.LONG , FormatStyle.SHORT ) , "" ); getLocaleFromGrid = true; } /** * Creates a new InstantRenderer. * <p> * The renderer is configured to render with the given formatter, with the * empty string as its null representation. * * @param formatter the formatter to use, not {@code null} * @throws IllegalArgumentException if formatter is null */ public InstantRenderer ( DateTimeFormatter formatter ) { this( formatter , "" ); } /** * Creates a new InstantRenderer. * <p> * The renderer is configured to render with the given formatter. * * @param formatter the formatter to use, not {@code null} * @param nullRepresentation the textual representation of the {@code null} value * @throws IllegalArgumentException if formatter is null */ public InstantRenderer ( DateTimeFormatter formatter , String nullRepresentation ) { super( Instant.class , nullRepresentation ); if ( formatter == null ) { throw new IllegalArgumentException( "formatter may not be null" ); } this.formatter = formatter; } /** * Creates a new InstantRenderer. * <p> * The renderer is configured to render with the given string format, as * displayed in the grid''s locale it is attached to, with an empty string as * its null representation. * * @param formatPattern the format pattern to format the date with, not {@code null} * @throws IllegalArgumentException if format pattern is null * @see <a href= * "https://docs.oracle.com/javase/8/docs/api/java/time/format/DateTimeFormatter.html#patterns"> * Format Pattern Syntax</a> */ public InstantRenderer ( String formatPattern ) { this( formatPattern , Locale.getDefault() ); getLocaleFromGrid = true; } /** * Creates a new InstantRenderer. * <p> * The renderer is configured to render with the given string format, as * displayed in the given locale, with an empty string as its null * representation. * * @param formatPattern the format pattern to format the date with, not {@code null} * @param locale the locale to use, not {@code null} * @throws IllegalArgumentException if format pattern is null * @throws IllegalArgumentException if locale is null * @see <a href= * "https://docs.oracle.com/javase/8/docs/api/java/time/format/DateTimeFormatter.html#patterns"> * Format Pattern Syntax</a> */ public InstantRenderer ( String formatPattern , Locale locale ) { this( formatPattern , locale , "" ); } /** * Creates a new InstantRenderer. * <p> * The renderer is configured to render with the given string format, as * displayed in the given locale. * * @param formatPattern the format pattern to format the date with, not {@code null} * @param locale the locale to use, not {@code null} * @param nullRepresentation the textual representation of the {@code null} value * @throws IllegalArgumentException if format pattern is null * @throws IllegalArgumentException if locale is null * @see <a href= * "https://docs.oracle.com/javase/8/docs/api/java/time/format/DateTimeFormatter.html#patterns"> * Format Pattern Syntax</a> */ public InstantRenderer ( String formatPattern , Locale locale , String nullRepresentation ) { super( Instant.class , nullRepresentation ); if ( formatPattern == null ) { throw new IllegalArgumentException( "format pattern may not be null" ); } if ( locale == null ) { throw new IllegalArgumentException( "locale may not be null" ); } formatter = DateTimeFormatter.ofPattern( formatPattern , locale ); } @Override public JsonValue encode ( Instant value ) { String dateString; if ( value == null ) { dateString = this.getNullRepresentation(); } else if ( this.getLocaleFromGrid ) { if ( null == this.getParentGrid() ) { throw new IllegalStateException( "Could not find a locale to format with: " + "this renderer should either be attached to a grid " + "or constructed with locale information" ); } ZonedDateTime zdt = value.atZone( this.zoneId ); // Basil Bourque. Locale locale = this.getParentGrid().getLocale(); dateString = zdt.format( formatter.withLocale( locale ) ); } else { ZonedDateTime zdt = value.atZone( this.zoneId ); // Basil Bourque. dateString = zdt.format( formatter ); } return encode( dateString , String.class ); } @Override protected InstantRendererState getState () { InstantRendererState s = ( InstantRendererState ) super.getState(); return s; } @Override protected InstantRendererState getState ( boolean markAsDirty ) { InstantRendererState s = ( InstantRendererState ) super.getState( markAsDirty ); return s; } }

InstantRendererConnector

/* * By Basil Bourque. Taken almost entirely from source code published by Vaadin Ltd. * * -------- * * Copyright 2000-2016 Vaadin Ltd. * * Licensed under the Apache License, Version 2.0 (the "License"); you may not * use this file except in compliance with the License. You may obtain a copy of * the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the * License for the specific language governing permissions and limitations under * the License. */ package com.basil.timepiece; import com.vaadin.shared.ui.Connect; /** * A connector for InstantRenderer. * <p> * The server-side Renderer operates on {@code Instant}s, but the data is * serialized as a string, and displayed as-is on the client side. This is to be * able to support the server''s locale. * * @author Vaadin Ltd * @since 8.1 */ @Connect( InstantRenderer.class ) public class InstantRendererConnector extends com.vaadin.client.connectors.grid.TextRendererConnector { @Override public InstantRendererState getState () { return ( InstantRendererState ) super.getState(); } }

InstantRendererState

/* * By Basil Bourque. Taken almost entirely from source code published by Vaadin Ltd. * * -------- * * Copyright 2000-2016 Vaadin Ltd. * * Licensed under the Apache License, Version 2.0 (the "License"); you may not * use this file except in compliance with the License. You may obtain a copy of * the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the * License for the specific language governing permissions and limitations under * the License. */ package com.basil.timepiece; /** * Shared state of InstantRenderer. * * @author Vaadin Ltd * @since 8.1 */ public class InstantRendererState extends com.vaadin.shared.ui.grid.renderers.TextRendererState { // This code intentionally left blank. }

Fuente en BitBucket

He publicado mi proyecto completo impulsado por Maven en BitBucket , todos los archivos necesarios para los procesadores de columna para Instant , OffsetDateTime y ZonedDateTime .

Solicitud de función

Publiqué el Issue n. ° 10208 Implementamos renderizadores de columna para Vaadin Grid para otros tipos de java.time (Instant, OffsetDateTime, ZonedDateTime) para complementar los representadores LocalDate y LocalDateTime en Vaadin 8.1. en la página Vaadin Framework GitHub.


Se requiere embalaje especial

Sí, se requiere un embalaje especial. No puede simplemente tirar las clases de implementación del renderizador de columna Vaadin Grid en una aplicación Vaadin regular.

Dos de las tres clases necesarias para la implementación de un generador de columnas implican el desarrollo del lado del cliente , en lugar del desarrollo habitual del lado del servidor que hacemos comúnmente en el trabajo de la aplicación Vaadin.

Afortunadamente, esto es más fácil de lo que parece. Para hacer un simple renderizador de columnas, Vaadin ofrece afortunadamente algunas superclases que hacen la mayor parte del trabajo pesado. Por lo tanto, no es necesario que conozcamos todos los detalles sangrientos de la magia de GWT y JavaScript que se esconde bajo las sábanas de Vaadin.

El camino al éxito implica:

vaadin-archetype-widget

Comience un nuevo proyecto utilizando un arquetipo Maven de varios módulos proporcionado por el equipo de Vaadin: vaadin-archetype-widget visto en esta lista .

módulo addon

Una vez que haya creado un proyecto a partir de ese arquetipo en su IDE , agregue sus clases de renderizador de tres columnas como se muestra en esta captura de pantalla para un renderizador Instant .

  • Renderer clase Renderer entra en el paquete principal del módulo ''complemento''.
  • Los archivos de clase RendererConnector & RendererState van en el paquete de client anidado del módulo ''addon''.

Por supuesto, en el trabajo real eliminaría el ejemplo MyComponent… archivos creados por el arquetipo.

módulo de demo

Una vez creado, puede probar el representador de columnas en la aplicación Vaadin del módulo "demostración" mediante la importación del paquete del módulo "complemento". En este caso:

import org.basilbourque.timecolrenderers.InstantRenderer;

Fuente de GitHub

Mi implementación exitosa de un renderizador de columna Instant se tomó completamente de tres clases relacionadas con LocalDateTimeRenderer provistas con el código fuente de Vaadin 8.1.3. Puede encontrar la versión actual de estas clases escribiendo LocalDateTimeRenderer en la función de búsqueda de archivos de GitHub .