Java / Vaadin - FormLayout自定义隐藏组件实现

时间:2017-07-10 19:53:17

标签: java vaadin vaadin-grid vaadin8

我正在使用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而不是组件。

This is how the view looks when trying to add the component directly

This is how it looks when using the quick and dirty fix (by adding and removing the component as needed), the form is not supposed to show here

And this is after clicking on the grid, this is how I want it to function

1 个答案:

答案 0 :(得分:4)

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

grid-table-wrapper-size

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

everything-full-size

所以,只是保持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);
}

hiding-showing-form-layout

P.S。如果有人可以通过提供有关如何计算尺寸的更多信息来改进此答案,请编辑此答案!