1

我正在 vaadin 开发一个 Web 应用程序,目前正在尝试实现一个地址簿。我查看了 github 上的官方实现,并试图以此为基础。

我遇到的问题是联系表格。我希望能够单击网格中的一行并打开一个包含信息的表单。(类似于在他们的示例中如何完成)

但是,该组件没有按预期做出反应。如果我将组件直接添加到主布局并尝试切换可见性,它会弄乱视图。我让它工作的唯一方法是根据需要添加和删除组件,尽管我不喜欢这个解决方案,也不优雅。

这是当前的实现

package com.example.ecenter.view;

import com.vaadin.data.Binder;
import com.vaadin.navigator.View;
import com.vaadin.navigator.ViewChangeListener.ViewChangeEvent;
import com.vaadin.spring.annotation.SpringComponent;
import com.vaadin.spring.annotation.SpringView;
import com.vaadin.ui.Button;
import com.vaadin.ui.FormLayout;
import com.vaadin.ui.Grid;
import com.vaadin.ui.HorizontalLayout;
import com.vaadin.ui.TextField;
import com.vaadin.ui.VerticalLayout;
import com.vaadin.ui.themes.ValoTheme;

import io.valhala.ecenter.temp.Client;

import java.util.Arrays;
import java.util.List;

@SpringView(name = AddressBookView.VIEW_NAME)
@SpringComponent
public class AddressBookView extends HorizontalLayout implements View
{
    public static final String VIEW_NAME = "Address Book";
    Grid<Client> contactList = new Grid<>(Client.class);
    private List<Client> clients = Arrays.asList(
        new Client("Sernie", "A", "123 Test St.", "test@gmail.gov", "555-555-5554"),
        new Client("Ernie", "B", "123 Test St.", "test@gmail.com", "555-555-5555"),
        new Client("Bernie", "C", "123 Test St.", "test@gmail.net", "555-555-5556"),
        new Client("Ayy", "Lmao", "123 Test St.", "test@gmail.org", "555-555-5557"),
        new Client("Dax", "E", "123 Test St.", "test@gmail.net", "555-555-5558"),
        new Client("Avorion", "F", "123 Test St.", "test@gmail.net", "555-555-5559"),
        new Client("Xanion", "G", "123 Test St.", "test@gmail.net", "555-555-5560"),
        new Client("Trinium", "H", "123 Test St.", "test@gmail.net", "555-555-5561"),
        new Client("Naonite", "I", "123 Test St.", "test@gmail.net", "555-555-5562"),
        new Client("Squillium", "J", "123 Test St.", "test@gmail.net", "555-555-5563"),
        new Client("Picard", "K", "123 Test St.", "test@gmail.net", "555-555-5564"),
        new Client("Richard", "L", "123 Test St.", "test@gmail.net", "555-555-5565"),
        new Client("Rickard", "M", "123 Test St.", "test@gmail.net", "555-555-5566"),
        new Client("Bobby", "N", "123 Test St.", "test@gmail.net", "555-555-5567"),
        new Client("Bob", "O", "123 Test St.", "test@gmail.net", "555-555-5568"),
        new Client("Ron", "P", "123 Test St.", "test@gmail.net", "555-555-5569"),
        new Client("Bill", "Q", "123 Test St.", "test@gmail.net", "555-555-5570"),
        new Client("Greg", "R", "123 Test St.", "test@gmail.net", "555-555-5571"),
        new Client("Juan", "S", "123 Test St.", "test@gmail.net", "555-555-5572"),
        new Client("Squidward", "T", "123 Test St.", "test@gmail.net", "555-555-5573"));

private ContactForm contactForm = new ContactForm();
private TextField filter = new TextField();
private Button addContact = new Button("New Client");

public AddressBookView()
{
    initConfig();
    buildLayout();
}

private void buildLayout() 
{
    HorizontalLayout actionBar = new HorizontalLayout(filter, addContact);
    actionBar.setWidth("100%");
    filter.setWidth("100%");
    actionBar.setExpandRatio(filter, 1);

    VerticalLayout left = new VerticalLayout(actionBar, contactList);
    left.setSizeFull();
    contactList.setSizeFull();
    left.setExpandRatio(contactList, 1);

    HorizontalLayout mainLayout = new HorizontalLayout(left);
    mainLayout.setSizeFull();
    mainLayout.setExpandRatio(left, 1);

    //HorizontalLayout test = new HorizontalLayout(contactForm);
    addComponent(mainLayout);

    //addComponent(test);
    /*
     * even using a different layout still messes it up
     */

    //contactForm.setVisible(false);
}

private void initConfig() 
{
    addContact.addClickListener(event -> 
    {
        addComponent(contactForm);
        contactForm.setClient(new Client());
    });

    filter.setPlaceholder("Search clients...");
    addContact.addStyleName(ValoTheme.BUTTON_PRIMARY);
    //filter.addValueChangeListener(e -> refreshContacts(e.getText()));

    contactList.setSelectionMode(Grid.SelectionMode.SINGLE);
    contactList.setColumns("firstName", "lastName");
    contactList.setItems(clients);

    contactList.asSingleSelect().addValueChangeListener(event -> 
    {
        if(event.getValue() == null)
        {
            removeComponent(contactForm); //quick and dirty workaround
        }
        else
        {
            addComponent(contactForm); //quick and dirty workaround
            /* contactForm.setVisible(true); messes up the entire view */
            contactForm.setClient(event.getValue());
        }
    });
}

@Override
public void enter(ViewChangeEvent event) {
}

private class ContactForm extends FormLayout
{
    private Client client;
    private Button save, delete, cancel;
    private TextField firstName, lastName, email, address, phoneNumber;
    private Binder<Client> binder = new Binder<>(Client.class);
    public ContactForm()
    {
        initConf();
        initLayout();
        setSizeUndefined();
        binder.bindInstanceFields(this);
    }

    public void initConf() 
    {
        save = new Button("Save");
        cancel = new Button("Cancel");

        firstName = new TextField();
        firstName.setPlaceholder("First Name");

        lastName = new TextField();
        lastName.setPlaceholder("Last Name");

        email = new TextField();
        email.setPlaceholder("Email Address");

        address = new TextField();
        address.setPlaceholder("Address");

        phoneNumber = new TextField();
        phoneNumber.setPlaceholder("Phone Number");

    }
    public void initLayout() 
    {
        HorizontalLayout actions = new HorizontalLayout(save, cancel);
        actions.setSpacing(true);

        addComponents(actions, firstName, lastName, email, address, phoneNumber);
    }

    public void setClient(Client client)
    {
        //setVisible(true);
        this.client = client;
        binder.setBean(client);
    }
  }
}

第一张图片显示了在将表单添加到布局并将其设置为隐藏时视图的反应。

第二张和第三张图片显示了视图应该如何反应。虽然为了达到预期的结果,我不得不做草率的编码。

最后的问题:

我该如何解决这个问题?我尝试过为表单使用内部类并将其创建为自己的类。我唯一的猜测是,在 github 实现中,他们将 UI 传递给地址簿扩展 UI 而不是组件的表单。

这是尝试直接添加组件时视图的外观

这是使用快速而肮脏的修复(通过根据需要添加和删除组件)时的外观,表单不应该在此处显示

这是在单击网格之后,这就是我希望它发挥作用的方式

4

1 回答 1

4

发生的情况是,您将视图(这是一个水平布局)的大小未定义并将大小设置为完整加上隐藏表单的组合会产生奇怪的结果。因此,如果您使用一些开发人员工具检查生成的元素,您会看到您的视图(水平布局)的高度为 147 像素,而网格表包装器的高度为 24 像素:

网格表包装器大小

如果您将视图高度设置为 100%,那么它将扩展以占据所有可用空间,这可能不是您想要的:

一切全尺寸

因此,只需保留left未定义的大小,并丢失mainLayout(您的视图已经扩展HorizontalLayout,所以只需使用它)并返回使用contactForm.setVisible(true/false). 这样,left布局将扩展以适应为操作栏 + 网格计算的任何大小:

private void buildLayout() {
    HorizontalLayout actionBar = new HorizontalLayout(filter, addContact);
    actionBar.setWidth("100%");
    filter.setWidth("100%");
    actionBar.setExpandRatio(filter, 1);

    VerticalLayout left = new VerticalLayout(actionBar, contactList);
    left.setSizeFull();
    left.setExpandRatio(contactList, 1);

    addComponents(left, contactForm);
    contactForm.setVisible(false);
}

隐藏显示表单布局


PS如果有人可以通过提供有关在这种情况下如何计算尺寸的更多见解来改进此答案,请编辑此答案!

于 2017-07-10T21:21:07.020 回答