【问题标题】:Implement a column renderer for Vaadin 8 Grid为 Vaadin 8 Grid 实现列渲染器
【发布时间】:2018-02-07 05:31:46
【问题描述】:

Vaadin Framework 指南在Vaadin Grid 中有一个page describing how to use Column Renderers。还有this page describes implementing renderers,但都太简短了。

我想实现一个InstantRenderer 来补充在 Vaadin 8.1 中添加的部分 java.time 渲染器集。为LocalDateLocalDateTime 添加了渲染器,但没有为InstantOffsetDateTimeZonedDateTime 添加渲染器。对于我的Instant 渲染器,我目前只是应用当前默认时区 (ZoneId) 来获得一个 ZonedDateTime,我在其上调用 toString 方法。还可以做更多,但这只是开始。

所以我的代码应该与提供的LocalDateTimeRenderer 非常相似。我正在尝试遵循该代码作为指南。

在搜索 Vaadin 源代码和阅读文档时,我似乎需要三段源代码:

我已经这样做了,它全部编译。但是我的表格无法渲染,我得到的只是页面上的一个白色空框。控制台或日志上不会出现任何错误。如果我删除我对InstantRenderer 的使用,并回退到让我的Instant 对象通过它们自己的toString 方法的默认值呈现,那么一切都很好,并且表格按预期显示。所以我知道我的自定义渲染器有问题。

当谈到“服务器端”与“客户端”Vaadin 时,我是一个新手。

➠ 我需要执行某种包装吗?目前,我的 Vaadin 项目中有我的三个类,以及 MyUI 源文件。

➠ 我是不是错过了一些其他的作品?

我通过调用无参数构造函数来实例化我的渲染器:

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

这是我上面列出的三个文件,几乎完全取自 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.
}

BitBucket 上的来源

我已经发布了我的complete Maven-driven project on BitBucketInstantOffsetDateTimeZonedDateTime 的列渲染器的所有必要文件。

功能请求

我在 Vaadin Framework GitHub 页面上发布了 Issue # 10208 Implement column renderers for Vaadin Grid for other java.time types (Instant, OffsetDateTime, ZonedDateTime) to complement the LocalDate & LocalDateTime renderers in Vaadin 8.1.

【问题讨论】:

  • 你试过?debug吗?

标签: datagrid vaadin renderer vaadin8


【解决方案1】:

需要特殊包装

是的,需要特殊包装。您不能简单地将 Vaadin Grid column renderer implementation 类扔到常规的 Vaadin 应用程序中。

列渲染器实现所需的三个类中的两个涉及client-side development,而不是我们在 Vaadin 应用程序工作中通常使用的server-side development

幸运的是,这比听起来容易。为了只做一个简单的列渲染器,幸运的是 Vaadin 提供了一些超类来完成大部分繁重的工作。因此,我们无需了解在 Vaadin 中隐藏的 GWTJavaScript 魔法的所有血腥细节。

成功之路包括:

vaadin-archetype-widget

使用 Vaadin 团队提供的 multi-module Maven archetype 开始一个新项目:vaadin-archetype-widget 见于 this list

addon模块

IDE 中根据该原型创建项目后,添加三列渲染器类,如 Instant 渲染器的屏幕截图所示。

  • Renderer 类位于“插件”模块的主包中。
  • RendererConnector & RendererState 类文件位于“插件”模块的嵌套 client 包中。

当然,在实际工作中,您会删除原型创建的示例 MyComponent… 文件。

demo模块

构建后,您可以通过导入“插件”模块的包在“演示”模块的 Vaadin 应用程序中尝试列渲染器。在这种情况下:

import org.basilbourque.timecolrenderers.InstantRenderer;

GitHub 源码

我成功实现 Instant 列渲染器完全取自 Vaadin 8.1.3 源代码提供的三个 LocalDateTimeRenderer 相关类。您可以通过在GitHub find file feature 中输入LocalDateTimeRenderer 来查找这些类的当前版本。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2017-08-22
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2018-12-20
    • 1970-01-01
    • 1970-01-01
    • 2017-08-31
    相关资源
    最近更新 更多