All Downloads are FREE. Search and download functionalities are using the official Maven repository.

com.vaadin.flow.component.grid.demo.GridDemo Maven / Gradle / Ivy

There is a newer version: 23.0.16
Show newest version
package com.vaadin.flow.component.grid.demo;

import static com.vaadin.flow.component.grid.demo.data.CountryData.UNITED_STATES;

import java.math.BigDecimal;
import java.text.NumberFormat;
import java.time.LocalDate;
import java.time.LocalDateTime;
import java.time.format.DateTimeFormatter;
import java.time.format.FormatStyle;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collection;
import java.util.Collections;
import java.util.HashMap;
import java.util.List;
import java.util.Locale;
import java.util.Map;
import java.util.Objects;
import java.util.Optional;
import java.util.Set;
import java.util.WeakHashMap;
import java.util.stream.Collectors;
import java.util.stream.Stream;

import org.apache.commons.lang3.StringUtils;

import com.vaadin.flow.component.ComponentEventListener;
import com.vaadin.flow.component.button.Button;
import com.vaadin.flow.component.checkbox.Checkbox;
import com.vaadin.flow.component.combobox.ComboBox;
import com.vaadin.flow.component.datepicker.DatePicker;
import com.vaadin.flow.component.dependency.JsModule;
import com.vaadin.flow.component.dialog.Dialog;
import com.vaadin.flow.component.formlayout.FormLayout;
import com.vaadin.flow.component.grid.ColumnTextAlign;
import com.vaadin.flow.component.grid.FooterRow;
import com.vaadin.flow.component.grid.Grid;
import com.vaadin.flow.component.grid.Grid.Column;
import com.vaadin.flow.component.grid.Grid.SelectionMode;
import com.vaadin.flow.component.grid.GridMultiSelectionModel;
import com.vaadin.flow.component.grid.GridSortOrder;
import com.vaadin.flow.component.grid.GridVariant;
import com.vaadin.flow.component.grid.HeaderRow;
import com.vaadin.flow.component.grid.HeaderRow.HeaderCell;
import com.vaadin.flow.component.grid.contextmenu.GridContextMenu;
import com.vaadin.flow.component.grid.contextmenu.GridMenuItem;
import com.vaadin.flow.component.grid.dataview.GridLazyDataView;
import com.vaadin.flow.component.grid.dataview.GridListDataView;
import com.vaadin.flow.component.grid.demo.data.CountryData;
import com.vaadin.flow.component.grid.demo.data.CustomerData;
import com.vaadin.flow.component.grid.demo.data.StatesData;
import com.vaadin.flow.component.grid.demo.data.TaskData;
import com.vaadin.flow.component.grid.demo.entity.Customer;
import com.vaadin.flow.component.grid.demo.entity.Task;
import com.vaadin.flow.component.grid.dnd.GridDragEndEvent;
import com.vaadin.flow.component.grid.dnd.GridDragStartEvent;
import com.vaadin.flow.component.grid.dnd.GridDropEvent;
import com.vaadin.flow.component.grid.dnd.GridDropLocation;
import com.vaadin.flow.component.grid.dnd.GridDropMode;
import com.vaadin.flow.component.grid.editor.Editor;
import com.vaadin.flow.component.html.Div;
import com.vaadin.flow.component.html.H3;
import com.vaadin.flow.component.html.Hr;
import com.vaadin.flow.component.html.Label;
import com.vaadin.flow.component.html.NativeButton;
import com.vaadin.flow.component.html.Span;
import com.vaadin.flow.component.orderedlayout.FlexComponent;
import com.vaadin.flow.component.orderedlayout.HorizontalLayout;
import com.vaadin.flow.component.orderedlayout.VerticalLayout;
import com.vaadin.flow.component.radiobutton.RadioButtonGroup;
import com.vaadin.flow.component.select.Select;
import com.vaadin.flow.component.textfield.TextArea;
import com.vaadin.flow.component.textfield.TextField;
import com.vaadin.flow.component.treegrid.TreeGrid;
import com.vaadin.flow.data.binder.Binder;
import com.vaadin.flow.data.converter.StringToIntegerConverter;
import com.vaadin.flow.data.provider.ListDataProvider;
import com.vaadin.flow.data.provider.hierarchy.TreeData;
import com.vaadin.flow.data.provider.hierarchy.TreeDataProvider;
import com.vaadin.flow.data.renderer.LocalDateRenderer;
import com.vaadin.flow.data.renderer.LocalDateTimeRenderer;
import com.vaadin.flow.data.renderer.NativeButtonRenderer;
import com.vaadin.flow.data.renderer.NumberRenderer;
import com.vaadin.flow.data.renderer.TemplateRenderer;
import com.vaadin.flow.data.validator.StringLengthValidator;
import com.vaadin.flow.data.value.ValueChangeMode;
import com.vaadin.flow.demo.DemoView;
import com.vaadin.flow.function.SerializableFunction;
import com.vaadin.flow.router.Route;

@Route("vaadin-grid")
@JsModule("@vaadin/flow-frontend/grid-demo-styles.js")
@SuppressWarnings("squid:S1192")
public class GridDemo extends DemoView {

    // begin-source-example
    // source-example-heading: Grid example model

    /**
     * Example object.
     */
    public static class Person implements Cloneable {
        private int id;
        private String firstName;
        private String lastName;
        private int age;
        private Address address;
        private String phoneNumber;
        private MaritalStatus maritalStatus;
        private LocalDate birthDate;
        private boolean isSubscriber;
        private String email;

        public Person() {

        }

        public Person(int id, String firstName, String lastName, int age,
                Address address, String phoneNumber) {
            super();
            this.id = id;
            this.firstName = firstName;
            this.lastName = lastName;
            this.age = age;
            this.address = address;
            this.phoneNumber = phoneNumber;
        }

        public Person(int id, String firstName, String lastName, int age,
                Address address, String phoneNumber,
                MaritalStatus maritalStatus, LocalDate birthDate) {
            super();
            this.id = id;
            this.firstName = firstName;
            this.lastName = lastName;
            this.age = age;
            this.address = address;
            this.phoneNumber = phoneNumber;
            this.maritalStatus = maritalStatus;
            this.birthDate = birthDate;
        }

        public int getId() {
            return id;
        }

        public void setId(int id) {
            this.id = id;
        }

        public String getFirstName() {
            return firstName;
        }

        public void setFirstName(String firstName) {
            this.firstName = firstName;
        }

        public String getLastName() {
            return lastName;
        }

        public void setLastName(String lastName) {
            this.lastName = lastName;
        }

        public int getAge() {
            return age;
        }

        public void setAge(int age) {
            this.age = age;
        }

        public String getPhoneNumber() {
            return phoneNumber;
        }

        public void setPhoneNumber(String phoneNumber) {
            this.phoneNumber = phoneNumber;
        }

        public Address getAddress() {
            return address;
        }

        public void setAddress(Address address) {
            this.address = address;
        }

        public MaritalStatus getMaritalStatus() {
            return maritalStatus;
        }

        public void setMaritalStatus(MaritalStatus maritalStatus) {
            this.maritalStatus = maritalStatus;
        }

        public LocalDate getBirthDate() {
            return birthDate;
        }

        public void setBirthDate(LocalDate birthDate) {
            this.birthDate = birthDate;
        }

        public String getImage() {
            return "https://randomuser.me/api/portraits/men/" + getId()
                    + ".jpg";
        }

        public boolean isSubscriber() {
            return isSubscriber;
        }

        public void setSubscriber(boolean isSubscriber) {
            this.isSubscriber = isSubscriber;
        }

        public String getEmail() {
            return email;
        }

        public void setEmail(String email) {
            this.email = email;
        }

        @Override
        public int hashCode() {
            return id;
        }

        @Override
        public boolean equals(Object obj) {
            if (this == obj)
                return true;
            if (!(obj instanceof Person)) {
                return false;
            }
            Person other = (Person) obj;
            return id == other.id;
        }

        @Override
        public String toString() {
            return String.format("%s, %s", firstName, lastName);
        }

        @Override
        public Person clone() { // NOSONAR
            try {
                return (Person) super.clone();
            } catch (CloneNotSupportedException e) {
                throw new RuntimeException(
                        "The Person object could not be cloned.", e);
            }
        }
    }

    public static class Address {
        private String street;
        private int number;
        private String postalCode;
        private String city;

        public Address() {

        }

        public Address(String postalCode, String city) {
            this.postalCode = postalCode;
            this.city = city;
        }

        public String getStreet() {
            return street;
        }

        public void setStreet(String street) {
            this.street = street;
        }

        public int getNumber() {
            return number;
        }

        public void setNumber(int number) {
            this.number = number;
        }

        public String getPostalCode() {
            return postalCode;
        }

        public void setPostalCode(String postalCode) {
            this.postalCode = postalCode;
        }

        public String getCity() {
            return city;
        }

        public void setCity(String city) {
            this.city = city;
        }

        @Override
        public String toString() {
            return String.format("%s %s", postalCode, city);
        }

    }

    public enum MaritalStatus {
        MARRIED, SINGLE;
    }

    // end-source-example

    public class PersonService {
        private PersonData personData = new PersonData();

        public List fetch(int offset, int limit) {
            int end = offset + limit;
            int size = personData.getPersons().size();
            if (size <= end) {
                end = size;
            }
            return personData.getPersons().subList(offset, end);
        }

        public Stream fetchPage(int page, int pageSize) {
            return personData.getPersons().stream().skip(page * pageSize)
                    .limit(pageSize);
        }

        public int count() {
            return personData.getPersons().size();
        }

        public List fetchAll() {
            return personData.getPersons();
        }
    }

    // begin-source-example
    // source-example-heading: Using Components in Grid

    /**
     * Component used for the cell rendering.
     */
    public static class PersonComponent extends Div {

        private String text;

        /**
         * Creates a new component with the given item.
         *
         * @param person
         *            the person to set
         */
        public PersonComponent(Person person) {
            setPerson(person);
        }

        /**
         * Sets the person for the component.
         *
         * @param person
         *            the person to be inside inside the cell
         */
        public void setPerson(Person person) {
            text = "Hi, i'm the component for " + person.getFirstName() + "!";
            setText(text);
        }
    }

    /**
     * Component used for the details row.
     */
    public static class PersonCard extends Div {

        /**
         * Constructor that takes a Person as parameter.
         *
         * @param person
         *            the person to be used inside the card
         */
        public PersonCard(Person person) {
            addClassName("custom-details");
            setId("person-card-" + person.getId());

            VerticalLayout layout1 = new VerticalLayout();
            layout1.add(new Label("Name: " + person.getFirstName()));
            layout1.add(new Label("Id: " + person.getId()));
            layout1.add(new Label("Age: " + person.getAge()));

            VerticalLayout layout2 = new VerticalLayout();
            layout2.add(
                    new Label("Street: " + person.getAddress().getStreet()));
            layout2.add(new Label(
                    "Address number: " + person.getAddress().getNumber()));
            layout2.add(new Label(
                    "Postal Code: " + person.getAddress().getPostalCode()));

            HorizontalLayout hlayout = new HorizontalLayout(layout1, layout2);
            hlayout.getStyle().set("border", "1px solid gray")
                    .set("padding", "10px").set("boxSizing", "border-box")
                    .set("width", "100%");

            add(hlayout);
        }
    }
    // end-source-example

    public static class Item {

        private String name;
        private double price;
        private LocalDateTime purchaseDate;
        private LocalDate EstimatedDeliveryDate;

        public Item() {
        }

        public Item(String name, double price, LocalDateTime purchaseDate,
                LocalDate estimatedDeliveryDate) {
            this.name = name;
            this.price = price;
            this.purchaseDate = purchaseDate;
            EstimatedDeliveryDate = estimatedDeliveryDate;
        }

        public String getName() {
            return name;
        }

        public void setName(String name) {
            this.name = name;
        }

        public double getPrice() {
            return price;
        }

        public void setPrice(double price) {
            this.price = price;
        }

        public LocalDateTime getPurchaseDate() {
            return purchaseDate;
        }

        public void setPurchaseDate(LocalDateTime purchaseDate) {
            this.purchaseDate = purchaseDate;
        }

        public LocalDate getEstimatedDeliveryDate() {
            return EstimatedDeliveryDate;
        }

        public void setEstimatedDeliveryDate(LocalDate estimatedDeliveryDate) {
            EstimatedDeliveryDate = estimatedDeliveryDate;
        }

        @Override
        public String toString() {
            return getName();
        }

    }

    public static class Order {

        private String name;
        private int numberOfOrder;
        private float price;
        private LocalDateTime purchaseDate;
        private LocalDate estimatedDeliveryDate;
        private String personName;
        private Address address;

        public Order(String name, int numberOfOrder, float price,
                LocalDateTime purchaseDate, LocalDate estimatedDeliveryDate,
                String personName, Address address) {
            this.name = name;
            this.numberOfOrder = numberOfOrder;
            this.price = price;
            this.purchaseDate = purchaseDate;
            this.estimatedDeliveryDate = estimatedDeliveryDate;
            this.personName = personName;
            this.address = address;
        }

        public String getName() {
            return name;
        }

        public void setName(String name) {
            this.name = name;
        }

        public float getPrice() {
            return price;
        }

        public void setPrice(float price) {
            this.price = price;
        }

        public LocalDateTime getPurchaseDate() {
            return purchaseDate;
        }

        public void setPurchaseDate(LocalDateTime purchaseDate) {
            this.purchaseDate = purchaseDate;
        }

        public LocalDate getEstimatedDeliveryDate() {
            return estimatedDeliveryDate;
        }

        public void setEstimatedDeliveryDate(LocalDate estimatedDeliveryDate) {
            this.estimatedDeliveryDate = estimatedDeliveryDate;
        }

        public String getPersonName() {
            return personName;
        }

        public void setPersonName(String personName) {
            this.personName = personName;
        }

        public int getNumberOfOrder() {
            return numberOfOrder;
        }

        public void setNumberOfOrder(int numberOfOrder) {
            this.numberOfOrder = numberOfOrder;
        }

        public Address getAddress() {
            return address;
        }

        public void setAddress(Address address) {
            this.address = address;
        }

    }

    public static class Benefit {

        private int year;
        private int quarter1;
        private int quarter2;
        private int quarter3;
        private int quarter4;

        public Benefit(int year, int quarter1, int quarter2, int quarter3,
                int quarter4) {

            this.year = year;
            this.quarter1 = quarter1;
            this.quarter2 = quarter2;
            this.quarter3 = quarter3;
            this.quarter4 = quarter4;
        }

        public int getYear() {
            return year;
        }

        public void setYear(int year) {
            this.year = year;
        }

        public int getQuarter1() {
            return quarter1;
        }

        public void setQuarter1(int quarter1) {
            this.quarter1 = quarter1;
        }

        public int getQuarter2() {
            return quarter2;
        }

        public void setQuarter2(int quarter2) {
            this.quarter2 = quarter2;
        }

        public int getQuarter3() {
            return quarter3;
        }

        public void setQuarter3(int quarter3) {
            this.quarter3 = quarter3;
        }

        public int getQuarter4() {
            return quarter4;
        }

        public void setQuarter4(int quarter4) {
            this.quarter4 = quarter4;
        }

    }

    @Override
    protected void initView() {
        createBasicUsage();// Basic Grid
        addVariantFeature();
        createGridWithLazyLoading(); // Lazy Loading
        createGridWithCustomItemCountEstimate();
        createGridWithExactItemCount();
        createGridWithPagedRepository();
        createSingleSelect(); // Selection
        createMultiSelect();
        createProgrammaticSelect();
        createGridWithSortableColumns();// Sorting
        createGridWithTextFieldFilters();// Filtering
        createGridWithDataTypeSpecificFilters();
        createConfiguringColumns();// Configuring Columns
        createManuallyDefiningColumns();
        createAutoWidthColumns();
        createFrozenColumns();
        createColumnAlignment();
        columnReorder();
        createHeaderAndFooter();// Header and footer
        createColumnGrouping();
        createHeaderAndFooterUsingComponents();
        createFormattingText();// Formatting contents
        createHtmlTemplateRenderer();
        createGridUsingComponent();// Using components
        createGridUsingComponentFilters();
        createGridWithItemDetails();
        createItemDetailsOpenedProgrammatically();
        createContextMenu();// Context Menu
        createContextSubMenu();// Context Sub Menu
        createDynamicContextMenu(); // Dynamic Context Menu
        createClickListener();// Click Listener
        createDoubleClickListener();
        createBufferedEditor();// Grid Editor
        createNotBufferedEditor();
        createBufferedDynamicEditor();
        createNotBufferedDynamicEditor();
        createRowReordering();
        createDragRowsBetweenGrids();
        createDropLocations();
        createDragData();
        createDragDropFilters();
        createExternalDataNavigation();
        createDynamicHeight();

        addCard("Grid example model",
                new Label("These objects are used in the examples above"));

        addCard("Using Components", "Using Components in Grid",
                new Label("These objects are used in the examples above"));
    }

    // Grid Basics begin
    private void createBasicUsage() {
        // begin-source-example
        // source-example-heading: Grid Basics
        List personList = new ArrayList<>();

        personList.add(new Person(100, "Lucas", "Kane", 68,
                new Address("12080", "Washington"), "127-942-237"));
        personList.add(new Person(101, "Peter", "Buchanan", 38,
                new Address("93849", "New York"), "201-793-488"));
        personList.add(new Person(102, "Samuel", "Lee", 53,
                new Address("86829", "New York"), "043-713-538"));
        personList.add(new Person(103, "Anton", "Ross", 37,
                new Address("63521", "New York"), "150-813-6462"));
        personList.add(new Person(104, "Aaron", "Atkinson", 18,
                new Address("25415", "Washington"), "321-679-8544"));
        personList.add(new Person(105, "Jack", "Woodward", 28,
                new Address("95632", "New York"), "187-338-588"));

        Grid grid = new Grid<>(Person.class);
        grid.setItems(personList);

        grid.removeColumnByKey("id");

        // The Grid<>(Person.class) sorts the properties and in order to
        // reorder the properties we use the 'setColumns' method.
        grid.setColumns("firstName", "lastName", "age", "address",
                "phoneNumber");

        // end-source-example
        grid.setId("basic-usage");

        addCard("Grid Basics", grid);
    }

    private void addVariantFeature() {
        // begin-source-example
        // source-example-heading: Theme variants usage
        List personList = getItems();
        Grid grid = new Grid<>();
        grid.setItems(personList);
        grid.addColumn(Person::getFirstName).setHeader("First Name");
        grid.addColumn(Person::getAge).setHeader("Age");
        grid.addThemeVariants(GridVariant.LUMO_NO_BORDER,
                GridVariant.LUMO_NO_ROW_BORDERS, GridVariant.LUMO_ROW_STRIPES);

        // end-source-example

        addVariantsDemo(() -> grid, Grid::addThemeVariants,
                Grid::removeThemeVariants, GridVariant::getVariantName,
                GridVariant.LUMO_NO_BORDER, GridVariant.LUMO_NO_ROW_BORDERS,
                GridVariant.LUMO_ROW_STRIPES);
    }

    // Lazy Loading Begin
    private void createGridWithLazyLoading() {
        // begin-source-example
        // source-example-heading: Grid with lazy loading
        Grid grid = new Grid<>();
        PersonService personService = new PersonService();

        /*
         * When provided a callback, the grid doesn't load all items from
         * backend to server memory right away. It will request only the data
         * that is shown in its current view "window". The data is provided
         * based on offset and limit.
         *
         * When the user scrolls to the end grid will automatically extend and
         * fetch more items until the backend runs out of items.
         */
        grid.setItems(query -> personService
                .fetch(query.getOffset(), query.getLimit()).stream());

        grid.addColumn(Person::getFirstName).setHeader("First Name");
        grid.addColumn(Person::getLastName).setHeader("Last Name");
        grid.addColumn(Person::getAge).setHeader("Age");

        // end-source-example
        grid.setId("lazy-loading");

        addCard("Lazy Loading", "Grid with lazy loading", grid);
    }

    private void createGridWithCustomItemCountEstimate() {
        // begin-source-example
        // source-example-heading: Fast Scroll with Custom Item Count Estimate
        // The backend will have 12345 items
        final ItemGenerator fakeBackend = new ItemGenerator(12345);
        Grid grid = new Grid<>();

        GridLazyDataView lazyDataView = grid.setItems(query -> fakeBackend
                .generateItems(query.getOffset(), query.getLimit()));
        /*
         * By default the grid will initially adjust the scrollbar to 200 items
         * and as the user scrolls down it automatically increases the size by
         * 200 until the backend runs out of items.
         *
         * Both the estimated item count and its increase can be customized to
         * allow the user to scroll down faster when the backend will have a lot
         * of items.
         */
        lazyDataView.setItemCountEstimate(1000);
        lazyDataView.setItemCountEstimateIncrease(1000);

        // Showing the item count for demo purposes
        Div countText = new Div();
        lazyDataView.addItemCountChangeListener(event -> {
            if (event.isItemCountEstimated()) {
                countText.setText(
                        "Item Count Estimate: " + event.getItemCount());
            } else {
                countText.setText("Exact Item Count: " + event.getItemCount());
            }
        });

        VerticalLayout layout = new VerticalLayout(grid, countText);

        grid.addColumn(Item::getName).setHeader("Name").setWidth("20px");
        grid.addColumn(new NumberRenderer<>(Item::getPrice, "$ %(,.2f",
                Locale.US, "$ 0.00")).setHeader("Price");
        grid.addColumn(new LocalDateTimeRenderer<>(Item::getPurchaseDate,
                DateTimeFormatter.ofLocalizedDateTime(FormatStyle.SHORT,
                        FormatStyle.MEDIUM)))
                .setHeader("Purchase Date and Time").setFlexGrow(2);
        grid.addColumn(new LocalDateRenderer<>(Item::getEstimatedDeliveryDate,
                DateTimeFormatter.ofLocalizedDate(FormatStyle.MEDIUM)))
                .setHeader("Estimated Delivery Date");
        // end-source-example

        grid.setId("custom-item-count-estimate");

        addCard("Lazy Loading", "Fast Scroll with Custom Item Count Estimate",
                layout);
    }

    private void createGridWithExactItemCount() {
        // begin-source-example
        // source-example-heading: Exact item count
        Grid grid = new Grid<>();
        PersonService personService = new PersonService();

        /*
         * In case it is desired to show to the user the exact number of items
         * in the backend, that can be done providing another callback that
         * fetches the item count from the backend.
         */
        GridLazyDataView lazyDataView = grid.setItems(
                query -> personService
                        .fetch(query.getOffset(), query.getLimit()).stream(),
                query -> personService.count());

        // The grid can be on switched back to unknown item count through the
        // API in the lazy data view:
        // lazyDataView.setItemCountUnknown();

        grid.addColumn(Person::getFirstName).setHeader("First Name");
        grid.addColumn(Person::getLastName).setHeader("Last Name");
        grid.addColumn(Person::getAge).setHeader("Age");
        // end-source-example

        grid.setId("count-callback");

        addCard("Lazy Loading", "Exact item count", grid);
    }

    private void createGridWithPagedRepository() {
        //@formatter:off
        // begin-source-example
        // source-example-heading: Loading from a paged repository

        Grid grid = new Grid<>();
        PersonService service = new PersonService();
        /*
         * For backends which provide data in pages, like Spring Data
         * repositories, it is possible to get the page number and size from the
         * Query API.
         * For more instructions on how to work with Spring Data,
         * see the documentation in https://vaadin.com/docs and the tutorials in
         * https://vaadin.com/learn/tutorials/.
         */
        grid.setItems(query -> service.fetchPage(query.getPage(),
                query.getPageSize())
        );

        grid.addColumn(Person::getFirstName).setHeader("First Name");
        grid.addColumn(Person::getLastName).setHeader("Last Name");
        grid.addColumn(Person::getAge).setHeader("Age");

        // end-source-example
        //@formatter:on
        grid.setId("paged-grid");
        addCard("Lazy Loading", "Loading from a paged repository", grid);
    }

    // Assigning Data Begin
    private void createArrayData() {
        // begin-source-example
        // source-example-heading: Assigning Array Data

        List personList = getItems();

        // Providing a bean-type generates columns for all of it's properties
        Grid grid = new Grid<>();
        grid.setItems(personList);

        Grid.Column firstNameColumn = grid
                .addColumn(Person::getFirstName).setHeader("First Name");
        Grid.Column lastNameColumn = grid.addColumn(Person::getLastName)
                .setHeader("Last Name");
        grid.addColumn(Person::getAge).setHeader("Age");

        Button addButton = new Button("Add Item", event -> {

            personList.add(new Person(10000, "X", "Y", 16,
                    new Address("95632", "New York"), "187-338-588"));
            // The dataProvider knows which List it is based on, so when you
            // edit the list
            // you edit the dataprovider.
            grid.getDataProvider().refreshAll();

        });

        Button removeButton = new Button("Remove last", event -> {

            personList.remove(personList.size() - 1);
            // The dataProvider knows which List it is based on, so when you
            // edit the list
            // you edit the dataprovider.
            grid.getDataProvider().refreshAll();
        });

        FooterRow footerRow = grid.appendFooterRow();
        footerRow.getCell(firstNameColumn).setComponent(addButton);
        footerRow.getCell(lastNameColumn).setComponent(removeButton);

        // end-source-example
        grid.setId("assigning-array-data");
        addButton.setId("assigning-array-data-add");
        removeButton.setId("assigning-array-data-remove");
        addCard("Assigning Data", "Assigning Array Data", grid, addButton,
                removeButton);
    }

    private void createDynamicHeight() {
        // begin-source-example
        // source-example-heading: Dynamic Height

        List personList = getItems();
        // Providing a bean-type generates columns for all of it's properties
        Grid grid = new Grid<>();

        // When using allRowsVisible, all items are fetched and
        // Grid uses all the space needed to render everything.
        //
        // Note: allRowsVisible disables the grid's virtual scrolling so that
        // all the rows are rendered in the DOM at once.
        // If the grid has a large number of items, using the feature is
        // discouraged to avoid performance issues.
        grid.setAllRowsVisible(true);

        final GridListDataView dataView = grid.setItems(personList);

        Grid.Column firstNameColumn = grid
                .addColumn(Person::getFirstName).setHeader("First Name");
        Grid.Column lastNameColumn = grid.addColumn(Person::getLastName)
                .setHeader("Last Name");
        Grid.Column ageColumn = grid.addColumn(Person::getAge)
                .setHeader("Age");

        Button addButton = new Button("Add Item",
                event -> dataView.addItem(new Person(106, "X", "Y", 16,
                        new Address("95632", "New York"), "187-338-588")));

        Button removeButton = new Button("Remove last", event -> dataView
                .removeItem(dataView.getItem(dataView.getItemCount() - 1)));

        FooterRow footerRow = grid.appendFooterRow();
        footerRow.getCell(firstNameColumn).setComponent(addButton);
        footerRow.getCell(lastNameColumn).setComponent(removeButton);

        // end-source-example
        grid.setId("dynamic-height");
        addButton.setId("dynamic-height-add");
        removeButton.setId("dynamic-height-remove");
        addCard("Dynamic Height", "Dynamic Height", grid, addButton,
                removeButton);
    }

    // Selection Begin
    private void createSingleSelect() {
        Div messageDiv = new Div();
        // begin-source-example
        // source-example-heading: Grid Single Selection
        List personList = getItems();
        Grid grid = new Grid<>();
        grid.setItems(personList);

        grid.addColumn(Person::getFirstName).setHeader("First Name");
        grid.addColumn(Person::getAge).setHeader("Age");

        grid.asSingleSelect().addValueChangeListener(event -> {
            String message = String.format("Selection changed from %s to %s",
                    event.getOldValue(), event.getValue());
            messageDiv.setText(message);
        });
        // end-source-example
        grid.setId("single-selection");
        messageDiv.setId("single-selection-message");
        addCard("Selection", "Grid Single Selection", grid, messageDiv);
    }

    private void createMultiSelect() {
        Div messageDiv = new Div();
        // begin-source-example
        // source-example-heading: Grid Multi Selection
        List personList = getItems();
        Grid grid = new Grid<>();
        grid.setItems(personList);

        grid.addColumn(Person::getFirstName).setHeader("First Name");
        grid.addColumn(Person::getAge).setHeader("Age");

        grid.setSelectionMode(SelectionMode.MULTI);

        grid.asMultiSelect().addValueChangeListener(event -> {
            String message = String.format("Selection changed from %s to %s",
                    event.getOldValue(), event.getValue());
            messageDiv.setText(message);
        });

        // You can pre-select items
        grid.asMultiSelect().select(personList.get(0), personList.get(1));
        // end-source-example
        grid.setId("multi-selection");
        messageDiv.setId("multi-selection-message");
        addCard("Selection", "Grid Multi Selection", grid, messageDiv);
    }

    private void createProgrammaticSelect() {
        // begin-source-example
        // source-example-heading: Grid with Programmatic Selection
        PersonService personService = new PersonService();
        List personList = personService.fetchAll();

        H3 firstHeader = new H3("Grid with single select");
        Grid firstGrid = new Grid<>();
        firstGrid.setItems(personList);

        H3 secondHeader = new H3("Grid with multi select");
        Grid secondGrid = new Grid<>();
        secondGrid.setItems(personList);
        secondGrid.setSelectionMode(SelectionMode.MULTI);

        TextField filterField = new TextField();
        filterField.setValueChangeMode(ValueChangeMode.EAGER);
        filterField.addValueChangeListener(event -> {
            Optional foundPerson = personList.stream()
                    .filter(person -> person.getFirstName().toLowerCase()
                            .startsWith(event.getValue().toLowerCase()))
                    .findFirst();

            firstGrid.asSingleSelect().setValue(foundPerson.orElse(null));

            secondGrid.getSelectionModel().deselectAll();
            Set foundpersons = personList.stream()
                    .filter(person -> person.getFirstName().toLowerCase()
                            .startsWith(event.getValue().toLowerCase()))
                    .collect(Collectors.toSet());
            secondGrid.asMultiSelect().setValue(foundpersons);
        });

        firstGrid.addColumn(Person::getFirstName).setHeader("First Name");
        firstGrid.addColumn(Person::getAge).setHeader("Age");

        secondGrid.addColumn(Person::getFirstName).setHeader("First Name");
        secondGrid.addColumn(Person::getAge).setHeader("Age");

        NativeButton deselectBtn = new NativeButton("Deselect all");
        deselectBtn.addClickListener(
                event -> secondGrid.asMultiSelect().deselectAll());
        NativeButton selectAllBtn = new NativeButton("Select all");
        selectAllBtn.addClickListener(
                event -> ((GridMultiSelectionModel) secondGrid
                        .getSelectionModel()).selectAll());
        // end-source-example
        filterField.setId("programmatic-select-filter");
        firstHeader.setId("programmatic-select-first-header");
        firstGrid.setId("programmatic-select");
        secondHeader.setId("programmatic-select-second-header");
        secondGrid.setId("programmatic-select-second-filter");
        selectAllBtn.setId("programmatic-select-select-all");
        deselectBtn.setId("programmatic-select-deselect");
        addCard("Selection", "Grid with Programmatic Selection", filterField,
                firstHeader, firstGrid, secondHeader, secondGrid, selectAllBtn,
                deselectBtn);
    }

    // Sorting Begin
    private void createGridWithSortableColumns() {
        Div messageDiv = new Div();
        // begin-source-example
        // source-example-heading: Grid with sortable columns
        List personList = getItems();
        Grid grid = new Grid<>();
        grid.setItems(personList);
        grid.setSelectionMode(SelectionMode.NONE);

        grid.addColumn(Person::getFirstName, "First Name")
                .setHeader("First Name");
        grid.addColumn(Person::getLastName, "Last Name").setHeader("Last Name");
        grid.addColumn(Person::getAge, "age").setHeader("Age");

        // addColumn is not Comparable so it uses toString method to sort the
        // column.
        grid.addColumn(TemplateRenderer. of(
                "
[[item.city]]
[[item.postalCode]]
") .withProperty("city", person -> person.getAddress().getCity()) .withProperty("postalCode", person -> person.getAddress().getPostalCode()), "city", "postalCode").setHeader("Address"); Checkbox multiSort = new Checkbox("Multiple column sorting enabled"); multiSort.addValueChangeListener( event -> grid.setMultiSort(event.getValue())); // you can set the sort order from server-side with the grid.sort method NativeButton invertAllSortings = new NativeButton( "Invert all sort directions", event -> { List> newList = grid.getSortOrder() .stream() .map(order -> new GridSortOrder<>(order.getSorted(), order.getDirection().getOpposite())) .collect(Collectors.toList()); grid.sort(newList); }); NativeButton resetAllSortings = new NativeButton("Reset all sortings", event -> grid.sort(null)); // end-source-example grid.setId("grid-sortable-columns"); multiSort.setId("grid-multi-sort-toggle"); invertAllSortings.setId("grid-sortable-columns-invert-sorting"); resetAllSortings.setId("grid-sortable-columns-reset-sorting"); messageDiv.setId("grid-sortable-columns-message"); addCard("Sorting", "Grid with sortable columns", grid, multiSort, messageDiv, invertAllSortings, resetAllSortings); } // Filtering private void createGridWithTextFieldFilters() { // begin-source-example // source-example-heading: Using text fields for filtering items List personList = getItems(); Grid grid = new Grid<>(); final GridListDataView dataView = grid.setItems(personList); Grid.Column firstNameColumn = grid .addColumn(Person::getFirstName).setHeader("Name"); Grid.Column ageColumn = grid.addColumn(Person::getAge) .setHeader("Age"); Grid.Column cityColumn = grid .addColumn(person -> person.getAddress().getCity()) .setHeader("City"); Grid.Column postalCodeColumn = grid .addColumn(person -> person.getAddress().getPostalCode()) .setHeader("Postal Code"); HeaderRow filterRow = grid.appendHeaderRow(); // First filter TextField firstNameField = new TextField(); firstNameField.addValueChangeListener(event -> dataView.addFilter( person -> StringUtils.containsIgnoreCase(person.getFirstName(), firstNameField.getValue()))); firstNameField.setValueChangeMode(ValueChangeMode.EAGER); filterRow.getCell(firstNameColumn).setComponent(firstNameField); firstNameField.setSizeFull(); firstNameField.setPlaceholder("Filter"); // Second filter TextField ageField = new TextField(); ageField.addValueChangeListener(event -> dataView .addFilter(person -> StringUtils.containsIgnoreCase( String.valueOf(person.getAge()), ageField.getValue()))); ageField.setValueChangeMode(ValueChangeMode.EAGER); filterRow.getCell(ageColumn).setComponent(ageField); ageField.setSizeFull(); ageField.setPlaceholder("Filter"); // Third filter TextField cityField = new TextField(); cityField.addValueChangeListener(event -> dataView .addFilter(person -> StringUtils.containsIgnoreCase( person.getAddress().getCity(), cityField.getValue()))); cityField.setValueChangeMode(ValueChangeMode.EAGER); filterRow.getCell(cityColumn).setComponent(cityField); cityField.setSizeFull(); cityField.setPlaceholder("Filter"); // Fourth filter TextField postalCodeField = new TextField(); postalCodeField.addValueChangeListener( event -> dataView.addFilter(person -> StringUtils .containsIgnoreCase(person.getAddress().getPostalCode(), postalCodeField.getValue()))); postalCodeField.setValueChangeMode(ValueChangeMode.EAGER); filterRow.getCell(postalCodeColumn).setComponent(postalCodeField); postalCodeField.setSizeFull(); postalCodeField.setPlaceholder("Filter"); // end-source-example grid.setId("grid-with-filters"); addCard("Filtering", "Using text fields for filtering items", grid); } // begin-source-example // source-example-heading: Using data type specific filtering private ComboBox maritalStatus; private DatePicker birthDateField; private VerticalLayout createGridWithFilters() { VerticalLayout layout = new VerticalLayout(); PersonService personService = new PersonService(); List personList = personService.fetchAll(); Grid grid = new Grid<>(); final GridListDataView dataView = grid.setItems(personList); final Column nameColumn = grid.addColumn(Person::getFirstName) .setHeader("Name"); grid.addColumn(Person::getAge).setHeader("Age"); grid.addColumn(Person::getBirthDate).setHeader("Birth Date"); grid.addColumn(person -> person.getAddress().getPostalCode()) .setHeader("Postal Code"); maritalStatus = new ComboBox<>("Filter by marital status: "); maritalStatus.setItems(MaritalStatus.values()); maritalStatus.setClearButtonVisible(true); birthDateField = new DatePicker("Filter by birth date: "); maritalStatus.addValueChangeListener(event -> applyFilter(dataView)); birthDateField.addValueChangeListener(event -> applyFilter(dataView)); final Label sizeLabel = new Label(); grid.appendFooterRow().getCell(nameColumn).setComponent(sizeLabel); // Show total amount of matching items dataView.addItemCountChangeListener( event -> sizeLabel.setText("Total: " + event.getItemCount())); layout.add(maritalStatus, birthDateField, grid); return layout; } private void applyFilter(GridListDataView dataView) { dataView.removeFilters(); if (birthDateField.getValue() != null) { dataView.addFilter(person -> Objects .equals(birthDateField.getValue(), person.getBirthDate())); } if (maritalStatus.getValue() != null) { dataView.addFilter(person -> maritalStatus.getValue() == person .getMaritalStatus()); } } // end-source-example private void createGridWithDataTypeSpecificFilters() { VerticalLayout layout = createGridWithFilters(); layout.setId("layout-with-filters"); addCard("Filtering", "Using data type specific filtering", layout); } // Configuring Columns Begin private void createConfiguringColumns() { // begin-source-example // source-example-heading: Configuring columns List personList = getItems(); // Providing a bean-type generates columns for all of it's properties Grid grid = new Grid<>(Person.class); // Property-names are automatically set as keys // You can remove undesired columns by using the key grid.removeColumnByKey("id"); // It could be used to specify columns order grid.setColumns("firstName", "lastName", "age", "address", "phoneNumber"); grid.setItems(personList); // Columns for sub-properties can be added easily grid.addColumn("address.postalCode"); // end-source-example grid.setId("configuring-columns"); addCard("Configuring columns", "Configuring columns", grid); } private void createManuallyDefiningColumns() { // begin-source-example // source-example-heading: Manually defining columns List personList = getItems(); Grid grid = new Grid<>(); grid.setSelectionMode(Grid.SelectionMode.MULTI); grid.setItems(personList); Grid.Column idColumn = grid.addColumn(Person::getId) .setHeader("ID").setFlexGrow(0).setWidth("75px"); // Combination of properties grid.addColumn( Person -> Person.getFirstName() + " " + Person.getLastName()) .setHeader("Full Name").setResizable(true); // Setting a column-key allows fetching the column later grid.addColumn(Person::getAge).setHeader("Age").setKey("age"); grid.getColumnByKey("age").setResizable(true); Checkbox idColumnVisibility = new Checkbox( "Toggle visibility of the ID column"); idColumnVisibility.addValueChangeListener( event -> idColumn.setVisible(!idColumn.isVisible())); Checkbox userReordering = new Checkbox( "Toggle user reordering of columns"); userReordering.addValueChangeListener(event -> grid .setColumnReorderingAllowed(!grid.isColumnReorderingAllowed())); // end-source-example grid.setId("column-api-example"); idColumnVisibility.setId("toggle-id-column-visibility"); userReordering.setId("toggle-user-reordering"); addCard("Configuring columns", "Manually defining columns", grid, new VerticalLayout(grid, idColumnVisibility, userReordering)); } private void createAutoWidthColumns() { // begin-source-example // source-example-heading: Columns with automatic width List personList = getItems(); Grid grid = new Grid<>(Person.class); grid.setItems(personList); grid.setColumns("firstName", "lastName", "age", "birthDate", "address", "phoneNumber"); grid.getColumns() .forEach(personColumn -> personColumn.setAutoWidth(true)); Button recalculateWidthsButton = new Button( "Recalculate column widths"); recalculateWidthsButton.addClickListener( buttonClickEvent -> grid.recalculateColumnWidths()); // end-source-example grid.setId("column-auto-width-grid"); recalculateWidthsButton.setId("column-auto-width-button"); addCard("Configuring columns", "Columns with automatic width", grid, recalculateWidthsButton); } private void createFrozenColumns() { // begin-source-example // source-example-heading: Frozen column example List personList = getItems(); H3 firstHeader = new H3("Freezing the selection column"); Grid firstGrid = new Grid<>(); firstGrid.setItems(personList); firstGrid.addColumn(Person::getId).setHeader("ID").setWidth("75px"); firstGrid.addColumn(Person::getFirstName).setHeader("First Name"); firstGrid.addColumn(Person::getLastName).setHeader("Last Name"); firstGrid.addColumn(Person::getPhoneNumber).setHeader("Phone Number") .setWidth("200px"); firstGrid.addColumn(Person::getAddress).setHeader("Adress") .setWidth("200px"); firstGrid.addColumn(Person::getMaritalStatus) .setHeader("Marital status").setWidth("200px"); firstGrid.addColumn(Person::getBirthDate).setHeader("Birth Date") .setWidth("200px"); firstGrid.setColumnReorderingAllowed(true); ((GridMultiSelectionModel) firstGrid .setSelectionMode(Grid.SelectionMode.MULTI)) // Freezing the selection column only .setSelectionColumnFrozen(true); H3 secondHeader = new H3("Freezing the data columns"); Grid secondGrid = new Grid<>(); secondGrid.setItems(personList); // Freezing any column secondGrid.addColumn(Person::getId).setHeader("ID").setWidth("75px") .setFrozen(true); secondGrid.addColumn(Person::getFirstName).setHeader("First Name") .setFrozen(true); secondGrid.addColumn(Person::getLastName).setHeader("Last Name") .setFrozen(true); secondGrid.addColumn(Person::getPhoneNumber).setHeader("Phone Number") .setWidth("200px"); secondGrid.addColumn(Person::getAddress).setHeader("Adress") .setWidth("200px"); secondGrid.addColumn(Person::getMaritalStatus) .setHeader("Marital status").setWidth("200px"); secondGrid.addColumn(Person::getBirthDate).setHeader("Birth Date") .setWidth("200px"); // end-source-example firstGrid.setId("frozen-column-first-grid"); secondGrid.setId("frozen-column-first-grid"); addCard("Configuring columns", "Frozen column example", firstHeader, firstGrid, secondHeader, secondGrid); } private void createColumnAlignment() { // begin-source-example // source-example-heading: Column alignment example List personList = getItems(); Grid grid = new Grid<>(); grid.setItems(personList); grid.addColumn(Person::getFirstName).setHeader("First Name"); // Setting a column-key allows fetching the column later grid.addColumn(Person::getAge).setHeader("Age").setKey("age"); grid.getColumnByKey("age"); RadioButtonGroup alignments = new RadioButtonGroup<>(); alignments.setItems(ColumnTextAlign.values()); alignments.setLabel("Text alignment for the Age column"); // ColumnTextAlign is a grid feature enum that is used to configure text // alignment inside columns. alignments.setValue(ColumnTextAlign.START); alignments.addValueChangeListener(event -> grid.getColumnByKey("age") .setTextAlign(event.getValue())); // end-source-example grid.setId("column-alignment-example"); alignments.setId("column-alignment-example-alignments"); addCard("Configuring columns", "Column alignment example", grid, alignments); } private void columnReorder() { // begin-source-example // source-example-heading: Column reorder example List personList = getItems(); Grid grid = new Grid<>(); grid.setItems(personList); grid.addColumn(Person::getFirstName).setHeader("First Name") .setKey("firstName"); grid.addColumn(Person::getLastName).setHeader("Last Name") .setKey("lastName"); grid.addColumn(Person::getAge).setHeader("Age").setKey("age"); grid.addColumn(Person::getEmail).setHeader("Email").setKey("email"); grid.addColumn(Person::getPhoneNumber).setHeader("Phone Number") .setKey("phoneNo"); grid.addColumn(Person::getBirthDate).setHeader("Birth Date") .setKey("birthDate"); Span columnOrder = new Span(); grid.setColumnReorderingAllowed(true); grid.addColumnReorderListener(event -> columnOrder .setText(event.getColumns().stream().map(Column::getKey) .collect(Collectors.joining(", ")))); // end-source-example grid.setId("column-reorder-example"); addCard("Configuring columns", "Column reorder example", grid, columnOrder); } // Header and footer begin private void createHeaderAndFooter() { // begin-source-example // source-example-heading: Header and footer texts List personList = getItems(); Grid grid = new Grid<>(); final GridListDataView dataView = grid.setItems(personList); grid.addColumn(Person::getFirstName).setHeader("First Name") .setFooter("Total: " + dataView.getItemCount() + " people"); long averageOfAge = Math.round(personList.stream() .mapToInt(Person::getAge).average().orElse(0)); grid.addColumn(Person::getAge).setHeader("Age") .setFooter("Average: " + averageOfAge); // end-source-example grid.setId("header-and-footer"); addCard("Header and footer", "Header and footer texts", grid); } private void createColumnGrouping() { // begin-source-example // source-example-heading: Column Grouping int sum = 200; List benefitList = new ArrayList<>(); benefitList.add(new Benefit(2017, sum, sum, sum, sum)); benefitList.add(new Benefit(2018, sum += 10, sum, sum, sum)); benefitList.add(new Benefit(2019, sum += 10, sum, sum, sum)); benefitList.add(new Benefit(2020, sum += 10, sum, sum, sum)); benefitList.add(new Benefit(2021, sum += 10, sum, sum, sum)); Grid grid = new Grid<>(); grid.setItems(benefitList); grid.addColumn(Benefit::getYear).setHeader("Year"); // Setting the alignment of columns Grid.Column quarter1 = grid.addColumn(Benefit::getQuarter1, "") .setHeader("Quarter 1").setTextAlign(ColumnTextAlign.END); Grid.Column quarter2 = grid.addColumn(Benefit::getQuarter2, "") .setHeader("Quarter 2").setTextAlign(ColumnTextAlign.END); Grid.Column quarter3 = grid.addColumn(Benefit::getQuarter3, "") .setHeader("Quarter 3").setTextAlign(ColumnTextAlign.END); Grid.Column quarter4 = grid.addColumn(Benefit::getQuarter4, "") .setHeader("Quarter 4").setTextAlign(ColumnTextAlign.END); HeaderRow halfheaderRow = grid.prependHeaderRow(); // Setting the alignment of only the header Div half1Header = new Div(new Span("Half 1")); half1Header.getStyle().set("text-align", "right"); half1Header.setSizeFull(); halfheaderRow.join(quarter1, quarter2).setComponent(half1Header); // Setting the alignment of only the header Div half2Header = new Div(new Span("Half 2")); half2Header.getStyle().set("text-align", "right"); half2Header.setSizeFull(); halfheaderRow.join(quarter3, quarter4).setComponent(half2Header); // Footers can be set with a similar API // end-source-example grid.setId("grid-with-header-and-footer"); addCard("Header and footer", "Column Grouping", grid); } private void createHeaderAndFooterUsingComponents() { // begin-source-example // source-example-heading: Using components Grid grid = new Grid<>(); final GridListDataView dataView = grid.setItems(getItems()); Grid.Column nameColumn = grid.addColumn(Person::getFirstName) .setHeader(new Label("Name")).setComparator((p1, p2) -> p1 .getFirstName().compareToIgnoreCase(p2.getFirstName())); Column ageColumn = grid.addColumn(Person::getAge, "age") .setHeader(new Label("Age")); Column streetColumn = grid .addColumn(person -> person.getAddress().getCity()) .setHeader(new Label("City")); Column postalCodeColumn = grid .addColumn(person -> person.getAddress().getPostalCode()) .setHeader(new Label("Postal Code")); // Create and combine the header HeaderRow topRow = grid.prependHeaderRow(); HeaderCell buttonsCell = topRow.join(nameColumn, ageColumn, streetColumn, postalCodeColumn); // Create and add buttons Button lessThanTwentyYearsold = new Button("-20 years old", event -> dataView.setFilter(person -> person.getAge() < 20)); Button twentyToForty = new Button("Between 20-40 years old", event -> dataView.setFilter(person -> (person.getAge() >= 20 && person.getAge() <= 40))); Button overForty = new Button("+40 years old", event -> dataView.setFilter(person -> person.getAge() > 40)); HorizontalLayout filter = new HorizontalLayout(lessThanTwentyYearsold, twentyToForty, overForty); buttonsCell.setComponent(filter); final Label sizeLabel = new Label(); grid.appendFooterRow().getCell(nameColumn).setComponent(sizeLabel); // Set the total amount of people when the size changes due to filters dataView.addItemCountChangeListener(event -> sizeLabel .setText("Total: " + event.getItemCount() + " people")); // end-source-example grid.setId("using-components"); addCard("Header and footer", "Using components", grid); } // Formatting contents private void createFormattingText() { // begin-source-example // source-example-heading: Formatting text List itemList = new ArrayList<>(); String str = "2016-03-04 11:30:40"; DateTimeFormatter formatter = DateTimeFormatter .ofPattern("yyyy-MM-dd HH:mm:ss"); LocalDateTime dateTime = LocalDateTime.parse(str, formatter); LocalDate localDate = LocalDate.parse(str, formatter); itemList.add(new Item("Car", 250, dateTime, localDate)); itemList.add(new Item("Flower", 10, dateTime, localDate)); itemList.add(new Item("Book", 210, dateTime, localDate)); itemList.add(new Item("Games", 250, dateTime, localDate)); Grid grid = new Grid<>(); grid.setItems(itemList); grid.addColumn(Item::getName).setHeader("Name").setWidth("20px"); // NumberRenderer to render numbers in general grid.addColumn(new NumberRenderer<>(Item::getPrice, "$ %(,.2f", Locale.US, "$ 0.00")).setHeader("Price"); // LocalDateTimeRenderer for date and time grid.addColumn(new LocalDateTimeRenderer<>(Item::getPurchaseDate, DateTimeFormatter.ofLocalizedDateTime(FormatStyle.SHORT, FormatStyle.MEDIUM))) .setHeader("Purchase Date and Time").setFlexGrow(2); // LocalDateRenderer for dates grid.addColumn(new LocalDateRenderer<>(Item::getEstimatedDeliveryDate, DateTimeFormatter.ofLocalizedDate(FormatStyle.MEDIUM))) .setHeader("Estimated Delivery Date"); // end-source-example grid.setId("grid-formatting-contents"); addCard("Formatting contents", "Formatting text", grid); } private void createHtmlTemplateRenderer() { // begin-source-example // source-example-heading: Grid with HTML template renderer List orderList = new ArrayList<>(); String str = "2016-03-04 11:30:40"; DateTimeFormatter formatter = DateTimeFormatter .ofPattern("yyyy-MM-dd HH:mm:ss"); LocalDateTime dateTime = LocalDateTime.parse(str, formatter); LocalDate localDate = LocalDate.parse(str, formatter); orderList.add(new Order("T-shirt", 2, 20, dateTime, localDate, "Mickael", new Address("12080", "Washington"))); orderList.add(new Order("Pant", 2, 70, dateTime, localDate, "Peter", new Address("93849", "New York"))); orderList.add(new Order("Bag", 1, 60, dateTime, localDate, "Samuel", new Address("86829", "New York"))); Grid grid = new Grid<>(); grid.setItems(orderList); grid.addColumn(Order::getName).setHeader("Buyer").setFlexGrow(1); NumberFormat moneyFormat = NumberFormat.getCurrencyInstance(Locale.US); // You can also set complex objects directly. Internal properties of the // bean are accessible in the template. grid.addColumn(TemplateRenderer. of( "
[[item.name]],[[item.price]]
purchased on: [[item.purchasedate]]
") .withProperty("name", Order::getName) // NumberRenderer to render numbers in general .withProperty("price", order -> moneyFormat.format(order.getPrice())) .withProperty("purchasedate", order -> formatter.format(order.getPurchaseDate()))) .setHeader("Purchase").setFlexGrow(6); grid.addColumn(TemplateRenderer. of( "
Estimated delivery date: [[item.estimatedDeliveryDate]]
to: [[item.address.city]],[[item.address.postalCode]]
") .withProperty("estimatedDeliveryDate", order -> formatter.format(order.getPurchaseDate())) .withProperty("address", order -> order.getAddress())) .setHeader("Delivery").setFlexGrow(6); // end-source-example grid.setId("template-renderer"); addCard("Formatting Contents", "Grid with HTML template renderer", grid); } // Using components begin private Grid createGridUsingComponent() { // begin-source-example // source-example-heading: Using Components List personList = getItems(); Grid grid = new Grid<>(); final GridListDataView dataView = grid.setItems(personList); // Use the component constructor that accepts an item -> // new PersonComponent(Person person) grid.addComponentColumn(PersonComponent::new).setHeader("Person"); // Or you can use an ordinary function to setup the component grid.addComponentColumn(item -> createRemoveButton(dataView, item)) .setHeader("Actions"); grid.setSelectionMode(Grid.SelectionMode.NONE); return grid; } private Button createRemoveButton(GridListDataView dataView, Person item) { Button button = new Button("Remove", clickEvent -> dataView.removeItem(item)); return button; } // end-source-example private void createGridUsingComponentFilters() { Grid grid = createGridUsingComponent(); grid.setId("using-components"); addCard("Using Components", "Using Components", grid); } // Item details private void createGridWithItemDetails() { // begin-source-example // source-example-heading: Grid with item details List personList = getItems(); H3 header = new H3("Clicking on a row will show more details"); Grid grid = new Grid<>(); grid.setItems(personList); grid.addColumn(Person::getFirstName).setHeader("First Name"); grid.addColumn(Person::getAge).setHeader("Age"); grid.setSelectionMode(Grid.SelectionMode.NONE); // You can use any renderer for the item details. By default, the // details are opened and closed by clicking the rows. grid.setItemDetailsRenderer(TemplateRenderer. of( "
" + "
Hi! My name is [[item.firstName]]!
" + "
" + "
") .withProperty("firstName", Person::getFirstName) .withProperty("lastname", Person::getLastName) .withProperty("address", Person::getAddress) .withProperty("image", Person::getImage) .withEventHandler("handleClick", person -> grid.getListDataView().refreshItem(person))); // end-source-example grid.setId("item-details"); header.setId("item-details-header"); addCard("Item details", "Grid with item details", header, grid); } private void createItemDetailsOpenedProgrammatically() { // begin-source-example // source-example-heading: Open details programmatically // Disable the default way of opening item details: List personList = getItems(); H3 header = new H3("Clicking on buttons will show more details"); Grid grid = new Grid<>(); grid.setItems(personList); grid.addColumn(Person::getFirstName).setHeader("First Name"); grid.addColumn(Person::getAge).setHeader("Age"); grid.setSelectionMode(Grid.SelectionMode.NONE); // You can use any renderer for the item details. By default, the // details are opened and closed by clicking the rows. grid.setItemDetailsRenderer(TemplateRenderer. of( "
" + "
Hi! My name is [[item.firstName]]!
" + "
") .withProperty("firstName", Person::getFirstName) // This is now how we open the details .withEventHandler("handleClick", person -> grid.getListDataView().refreshItem(person))); // Disable the default way of opening item details: grid.setDetailsVisibleOnClick(false); grid.addColumn(new NativeButtonRenderer<>("Details", item -> grid .setDetailsVisible(item, !grid.isDetailsVisible(item)))); // end-source-example grid.setId("open-details-programmatically"); header.setId("open-details-programmatically-header"); addCard("Item details", "Open details programmatically", header, grid); } // begin-source-example // source-example-heading: Navigating grid items externally // Clicking on item in grid opens dialog for item navigation private Grid createExternalDataNavigationGrid() { Grid grid = new Grid<>(Person.class); final GridListDataView dataView = grid .setItems(new PersonService().fetchAll()); grid.removeColumnByKey("id"); // The Grid<>(Person.class) sorts the properties and in order to // reorder the properties we use the 'setColumns' method. grid.setColumns("firstName", "lastName", "age", "address", "phoneNumber"); grid.addItemClickListener( event -> new DataDialog(dataView, event.getItem()).open()); return grid; } private class DataDialog extends Dialog { private Button next; private Button previous; private Person currentItem; private final GridListDataView dataView; private Span data = new Span(); public DataDialog(GridListDataView dataView, Person item) { this.dataView = dataView; next = new Button("Next", event -> setItem(dataView.getNextItem(currentItem).get())); previous = new Button("Previous", event -> setItem( dataView.getPreviousItem(currentItem).get())); setItem(item); setModal(true); HorizontalLayout layout = new HorizontalLayout(previous, data, next); layout.expand(data); layout.setAlignItems(FlexComponent.Alignment.CENTER); layout.setWidth("400px"); add(new VerticalLayout(new Span("Click outside to close"), layout)); } private void setItem(Person item) { currentItem = item; data.setText(String.format("%s %s", item.getFirstName(), item.getLastName())); next.setEnabled(dataView.getNextItem(currentItem).isPresent()); previous.setEnabled( dataView.getPreviousItem(currentItem).isPresent()); } } // end-source-example private void createExternalDataNavigation() { Grid grid = createExternalDataNavigationGrid(); grid.setId("external-item-navigation"); addCard("Item details", "Navigating grid items externally", grid); } // Context Menu begin private void createContextMenu() { TextArea message = new TextArea(""); message.setHeight("100px"); message.setReadOnly(true); TaskData taskData = new TaskData(); List taskList = taskData.getTasks(); DateTimeFormatter formatter = DateTimeFormatter.ofPattern("MM/dd/yyyy"); // begin-source-example // source-example-heading: Using ContextMenu With Grid Grid grid = new Grid<>(); List tasks = taskData.getTasks(); GridListDataView dataView = grid.setItems(tasks); grid.addColumn(Task::getName).setHeader("Task Name"); grid.addColumn(Task::getDueDate).setHeader("Due Date"); GridContextMenu contextMenu = new GridContextMenu<>(grid); GridMenuItem insert = contextMenu.addItem("Insert"); insert.getSubMenu().addItem("Add a task before", event -> event .getItem() .ifPresent(item -> dataView.addItemBefore( new Task(100, "New Task", LocalDate.parse("02/01/2019", formatter)), item))); insert.getSubMenu().add(new Hr()); insert.getSubMenu().addItem("Add a task after", event -> event.getItem() .ifPresent(item -> dataView.addItemAfter( new Task(100, "New Task", LocalDate.parse("02/01/2019", formatter)), item))); contextMenu.addItem("Remove", event -> event.getItem().ifPresent(dataView::removeItem)); contextMenu.addGridContextMenuOpenedListener(event -> message.setValue( String.format("Menu opened on\n Row: '%s'\n Column: '%s'", event.getItem().map(Task::toString).orElse("-no item-"), event.getColumnId().orElse("-no column-")))); // end-source-example grid.setId("context-menu-grid"); addCard("Context Menu", "Using ContextMenu With Grid", grid, contextMenu, message); } // Context sub Menu begin private void createContextSubMenu() { // begin-source-example // source-example-heading: Using Context Sub Menu With Grid Grid grid = new Grid<>(); final GridListDataView dataView = grid .setItems(new PersonService().fetchAll()); grid.addColumn(Person::getFirstName).setHeader("First Name"); grid.addColumn(Person::getAge).setHeader("Age"); GridContextMenu contextMenu = new GridContextMenu<>(grid); GridMenuItem insert = contextMenu.addItem("Insert"); insert.getSubMenu().addItem("Insert a row above", event -> { Optional item = event.getItem(); if (!item.isPresent()) { // no selected row return; } dataView.addItemBefore(item.get(), createItems(1).get(0)); }); insert.getSubMenu().add(new Hr()); insert.getSubMenu().addItem("Insert a row below", event -> { Optional item = event.getItem(); if (!item.isPresent()) { // no selected row return; } dataView.addItemAfter(item.get(), createItems(1).get(0)); }); // end-source-example grid.setId("context-sub-menu-grid"); addCard("Context Menu", "Using Context Sub Menu With Grid", grid, contextMenu); } // Dynamic Context Menu begin private void createDynamicContextMenu() { TaskData taskData = new TaskData(); // begin-source-example // source-example-heading: Dynamic Context Menu Grid grid = new Grid<>(); grid.setItems(taskData.getTasks()); grid.addColumn(Task::getName).setHeader("Task Name"); grid.addColumn(Task::getDueDate).setHeader("Due Date"); GridContextMenu contextMenu = new GridContextMenu<>(grid); contextMenu.setDynamicContentHandler(task -> { if (task == null) { // do not show the context menu when a row is not clicked return false; } contextMenu.removeAll(); contextMenu.addItem("Name: " + task.getName()); contextMenu.addItem("Due date: " + task.getDueDate()); return true; // show the context menu }); // end-source-example grid.setId("dynamic-context-menu-grid"); addCard("Context Menu", "Dynamic Context Menu", grid, contextMenu); } // Click Listener Begin private void createClickListener() { FormLayout formLayout = new FormLayout(); Label name = new Label(); Label age = new Label(); Label column = new Label(); // begin-source-example // source-example-heading: Item Click Listener Grid grid = new Grid<>(); grid.setItems(getItems()); grid.addColumn(Person::getFirstName).setHeader("First Name") .setKey("First Name"); grid.addColumn(Person::getAge).setHeader("Age").setKey("Age"); // Disable selection: will receive only click events instead grid.setSelectionMode(Grid.SelectionMode.NONE); formLayout.add(name, age); formLayout.addFormItem(name, "Name"); formLayout.addFormItem(age, "Age"); formLayout.addFormItem(column, "Column"); grid.addItemClickListener(event -> { name.setText(event.getItem().getFirstName()); age.setText(String.valueOf(event.getItem().getAge())); column.setText(event.getColumn().getKey()); }); // end-source-example grid.setId("item-click-listener"); addCard("Click Listeners", "Item Click Listener", grid, formLayout); } private void createDoubleClickListener() { Div message = new Div(); message.setId("doubleclicked-item"); FormLayout formLayout = new FormLayout(); Label name = new Label(); Label age = new Label(); // begin-source-example // source-example-heading: Item Double Click Listener Grid grid = new Grid<>(); grid.setItems(getItems()); grid.addColumn(Person::getFirstName).setHeader("First Name"); grid.addColumn(Person::getAge).setHeader("Age"); formLayout.add(name, age); formLayout.addFormItem(name, "Name"); formLayout.addFormItem(age, "Age"); grid.addItemDoubleClickListener(event -> { name.setText(event.getItem().getFirstName()); age.setText(String.valueOf(event.getItem().getAge())); }); // end-source-example grid.setId("item-doubleclick-listener"); message.addClickListener(event -> message.setText("")); addCard("Click Listeners", "Item Double Click Listener", grid, formLayout); } // Grid Editor private void createBufferedEditor() { PersonService personService = new PersonService(); List personList = personService.fetchAll(); Div message = new Div(); message.setId("buffered-editor-msg"); // begin-source-example // source-example-heading: Editor in Buffered Mode Grid grid = new Grid<>(); List persons = getItems(); grid.setItems(persons); Grid.Column firstNameColumn = grid .addColumn(Person::getFirstName).setHeader("First Name"); Grid.Column ageColumn = grid.addColumn(Person::getAge) .setHeader("Age"); Binder binder = new Binder<>(Person.class); Editor editor = grid.getEditor(); editor.setBinder(binder); editor.setBuffered(true); Div validationStatus = new Div(); validationStatus.setId("validation"); TextField firstNameField = new TextField(); binder.forField(firstNameField) .withValidator(new StringLengthValidator( "First name length must be between 3 and 50.", 3, 50)) .withStatusLabel(validationStatus).bind("firstName"); firstNameColumn.setEditorComponent(firstNameField); TextField ageField = new TextField(); binder.forField(ageField) .withConverter( new StringToIntegerConverter("Age must be a number.")) .withStatusLabel(validationStatus).bind("age"); ageColumn.setEditorComponent(ageField); Collection




© 2015 - 2024 Weber Informatics LLC | Privacy Policy