首页 > 解决方案 > Vaadin 14 datagrid 中的项目详细信息数据渲染不正确

问题描述

我在数据网格上的 ItemDetails 视图出现渲染问题。我需要过滤所选父项的详细信息项。在我过滤项目然后细节项目停止正确渲染之前,它工作正常。有时父项和第一个细节项之间存在巨大差距。

差距大

有时细节项将呈现在父项的标题下。

数据在网格标题下上升

但是当我查看页面源时,数据肯定在页面中。我已经尝试了我能想到的一切,以使这项工作正确地明确下来,为具有相同结果的数据创建一个原始模板化 html 表。还没有找到它不会发生的浏览器。删除所有 css 样式没有帮助。但是,简单地选择任何一个父项将导致网格再次正确呈现,因此一种想法可能是使用客户端事件重新呈现网格。(如果这甚至是可能的?)

我已将代码简化为如此简单,以至于很难理解为什么会发生这种情况。另外,我使用 AbstractBackEndDataProvider 作为数据提供者。这是我可能失败的非常基本的示例。

package com.imapvidsoft.partnerportal.ui;

import java.util.List;
import java.util.Random;
import java.util.stream.Collectors;

import com.imapvidsoft.common.pojo.ChannelType;
import com.imapvidsoft.common.utility.Utility;
import com.imapvidsoft.partner.Partner;
import com.imapvidsoft.partner.PartnerDevice;
import com.imapvidsoft.partnerportal.authentication.CurrentUser;
import com.google.common.collect.Lists;
import com.vaadin.flow.component.AttachEvent;
import com.vaadin.flow.component.Component;
import com.vaadin.flow.component.grid.Grid;
import com.vaadin.flow.component.html.Label;
import com.vaadin.flow.component.orderedlayout.HorizontalLayout;
import com.vaadin.flow.component.orderedlayout.VerticalLayout;
import com.vaadin.flow.component.select.Select;
import com.vaadin.flow.data.renderer.ComponentRenderer;
import com.vaadin.flow.data.renderer.TemplateRenderer;
 
@SuppressWarnings("serial")
public class DeviceGrid extends Grid<PartnerDevice> 
{
    @Override protected void onAttach(AttachEvent attachEvent) 
    {
        super.onAttach(attachEvent);
        drawUI();       // defers building the UI until the partner is logged in
    }

    private void drawUI()
    {                     
        Partner user = CurrentUser.get();
        Utility.Verify(user != null, "User should be logged in");
        
        addColumn(device -> device.Description)
            .setHeader("Description")
            .setResizable(true);
        
        addComponentColumn( device  ->  new Label(device.getUsagekWhs() == null ? "" : device.getUsagekWhs() + " kWh"))
            .setHeader(buildDeviceTypeDropDown())
            .setResizable(true);
        
        
        // Pick one
        setItemDetailsRenderer(new ComponentRenderer<Component, PartnerDevice>( __ -> getComponentTable()));
        
        /*
        setItemDetailsRenderer(TemplateRenderer.<PartnerDevice> of(
                       "<div style=\"border: 1px solid gray; width: 100%;\"inner-h-t-m-l=\"[[item.html]]\"></div>")
                .withProperty("html", __ -> getHtmlTable()));
        */
    }
                
    
    private Component buildDeviceTypeDropDown() {
        final PartnerDeviceDataProvider _dataProvider = (PartnerDeviceDataProvider)this.getDataProvider();        
        final Select<ChannelType> channelType = new Select<>();
                
        channelType.setEmptySelectionAllowed(true);
        channelType.setEmptySelectionCaption("ALL");                
        channelType.setItems( _dataProvider.getChannelTypes() );
        channelType.setTextRenderer(e -> e.getDescription());
        channelType.addValueChangeListener(event -> 
        { 
            _dataProvider.setChannelTypeFilter( event.getValue() );         
        });
        
        return channelType; 
    }
    
    private static String TD = "<td style=\"border: 1px solid lightgrey; width: 33.3%; padding: 3px;\">";
    private static String TABLEHEADER = "<tr>" + TD + "<b>ID</b></td>" + TD + "<b>Description</b></td></tr>";
    private String getHtmlTable() 
    {
        Random rand = new Random();
        List<ChannelUsage> usages = Lists.newArrayList();
        int randomNum = rand.nextInt((20 - 1) + 1) + 1;  // 
        
        for(int i=0; i < randomNum; i++) {
             usages.add(new ChannelUsage(i));                
        }
         
        String table = "<table style=\"width: 100%\">" + TABLEHEADER
        + usages.stream().map(e -> "<tr>" 
        + TD + e.getId() + "</td>" 
        + TD + e.getDescription() + "</td>")
        .collect(Collectors.joining("</tr>"))
        + "</table>";
        return table;
    }
    
    private Component getComponentTable() 
    {
        Random rand = new Random();
        List<ChannelUsage> usages = Lists.newArrayList();
        int randomNum = rand.nextInt((20 - 1) + 1) + 1;  // 
        
        for(int i=0; i < randomNum; i++) {
             usages.add(new ChannelUsage(i));                
        }
        
        VerticalLayout grid = new VerticalLayout();
        for(ChannelUsage channel : usages)
        {
            HorizontalLayout row = new HorizontalLayout();
            row.add(new Label(channel.getId() + "_id"));
            row.add(new Label(channel.getDescription()));           
            grid.add(row);
        }
        return grid;
    }
        
    private class ChannelUsage 
    {
        final int _id;
        
        ChannelUsage(Integer id) 
        {
            _id = id;           
        }
        
        private int getId() 
        {
            return _id;
        }
        
        private String getDescription()
        {           
            return "Channel desc " + _id;
        }
    
    }   
}

标签: datagriddetailsviewvaadin14

解决方案


推荐阅读