Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Filter icon custom #28

Merged
merged 2 commits into from
Dec 23, 2022
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
22 changes: 22 additions & 0 deletions enhanced-grid-flow-demo/frontend/icons/enhancedgridiconsettest.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
import '@vaadin/icon/vaadin-iconset.js';

const template = document.createElement('template');

template.innerHTML = `<vaadin-iconset name="enhancedgridiconsettest" size="24">
<svg><defs>
<g id="enhancedgridiconsettest:filtericon"><svg xmlns="http://www.w3.org/2000/svg" class="icon icon-tabler icon-tabler-adjustments-horizontal" width="24" height="24" viewBox="0 0 24 24" stroke-width="1.5" stroke="#2c3e50" fill="none" stroke-linecap="round" stroke-linejoin="round">
<path stroke="none" d="M0 0h24v24H0z" fill="none"/>
<circle cx="14" cy="6" r="2" />
<line x1="4" y1="6" x2="12" y2="6" />
<line x1="16" y1="6" x2="20" y2="6" />
<circle cx="8" cy="12" r="2" />
<line x1="4" y1="12" x2="6" y2="12" />
<line x1="10" y1="12" x2="20" y2="12" />
<circle cx="17" cy="18" r="2" />
<line x1="4" y1="18" x2="15" y2="18" />
<line x1="19" y1="18" x2="20" y2="18" />
</svg></g>
</defs></svg>
</vaadin-iconset>`;

document.head.appendChild(template.content);
Original file line number Diff line number Diff line change
@@ -0,0 +1,134 @@
package com.vaadin.componentfactory.enhancedgrid;

import java.util.Comparator;
import java.util.List;

import com.vaadin.componentfactory.enhancedgrid.bean.Person;
import com.vaadin.componentfactory.enhancedgrid.filtering.TextFieldFilterDto;
import com.vaadin.componentfactory.enhancedgrid.filtering.TextFilterField;
import com.vaadin.componentfactory.enhancedgrid.iconset.EnhancedGridIconsetTest;
import com.vaadin.componentfactory.enhancedgrid.service.PersonService;
import com.vaadin.flow.component.button.Button;
import com.vaadin.flow.component.grid.Grid;
import com.vaadin.flow.component.grid.GridSortOrder;
import com.vaadin.flow.component.grid.GridSortOrderBuilder;
import com.vaadin.flow.component.grid.editor.Editor;
import com.vaadin.flow.component.html.Div;
import com.vaadin.flow.component.html.Paragraph;
import com.vaadin.flow.component.orderedlayout.FlexComponent.JustifyContentMode;
import com.vaadin.flow.component.orderedlayout.HorizontalLayout;
import com.vaadin.flow.component.textfield.TextField;
import com.vaadin.flow.data.binder.Binder;
import com.vaadin.flow.data.renderer.NumberRenderer;
import com.vaadin.flow.router.Route;

/**
* Basic single selection grid example with setItems, editing, filtering, sorting and a custom filter icon.
*/
@Route(value = "custom-filter-icon", layout = MainLayout.class)
public class CustomFilterIconView extends Div {

public CustomFilterIconView() {
add(new Paragraph("Basic single selection grid example with editing, filtering, sorting and a custom filter icon"));

Div messageDiv = new Div();

List<Person> personList = getItems();
EnhancedGrid<Person> grid = new EnhancedGrid<>();

// set selection predicate to indicate which items can be selected
grid.setSelectionPredicate(p -> p.getAge() > 18);
grid.setItems(personList);

// add columns
// first name column with filtering button on header
EnhancedColumn<Person> firstNameColumn = grid.addColumn(Person::getFirstName).setHeader("First Name", new TextFilterField()).setResizable(true);
// last name column with filtering button and pre-selected filter by last name = "Allen"
grid.addColumn(Person::getLastName).setHeader("Last Name", new TextFilterField(new TextFieldFilterDto("Allen"))).setResizable(true);
// age column with renderer
NumberRenderer<Person> ageRenderer = new NumberRenderer<Person>(Person::getAge, "Age: %d");
EnhancedColumn<Person> ageColumn = grid.addColumn(ageRenderer).setComparator(Comparator.comparing(Person::getAge)).setHeader("Age", new TextFilterField());
ageColumn.setValueProvider(p -> String.valueOf(p.getAge()));

// add pre-selected descendent order for first name column
List<GridSortOrder<Person>> sortByFirstName = new GridSortOrderBuilder<Person>()
.thenDesc(firstNameColumn).build();
grid.sort(sortByFirstName);

// set selection mode
grid.setSelectionMode(Grid.SelectionMode.SINGLE);

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

// can pre-select items
grid.select(personList.get(0));

// set editable predicate to indicate which items can be edited
grid.setEditablePredicate(p -> p.getAge() > 18);

Binder<Person> binder = new Binder<>(Person.class);
Editor<Person> editor = grid.getEditor();
editor.setBinder(binder);
editor.setBuffered(true);

// define editor components for columns
TextField firstNameField = new TextField();
binder.bind(firstNameField, Person::getFirstName, Person::setFirstName);
firstNameColumn.setEditorComponent(firstNameField);

// call edit
grid.addItemDoubleClickListener(event -> {
grid.editItem(event.getItem());
firstNameField.focus();
});

// cancel edit
grid.getElement().addEventListener("keyup",
event -> editor.cancel())
.setFilter("event.key === 'Escape' || event.key === 'Esc'");

// add column with save button, to invoke when editing item
grid.addComponentColumn(person -> {
Button save = new Button("Save");

save.addClickListener(e -> {
editor.save();
firstNameField.focus();
});
save.setEnabled(editor.isOpen());
return save;
});

// show save item message
editor.addSaveListener(
event -> messageDiv.setText("Item saved: " + event.getItem().getFirstName() + ", "
+ event.getItem().getLastName() + ", "
+ event.getItem().getAge()));

// add layout for buttons
HorizontalLayout horizontalLayout = new HorizontalLayout();
horizontalLayout.setWidthFull();
horizontalLayout.setJustifyContentMode(JustifyContentMode.END);
// add button to clear all selected filters
Button clearFiltersButton = new Button("Clear Filters", e -> grid.clearAllFilters());
horizontalLayout.add(clearFiltersButton);
// add button to clear all sorting
Button clearSortingButton = new Button("Clear Sorting", e -> grid.sort(null));
horizontalLayout.add(clearSortingButton);

// set custom filter icon
grid.setFilterIcon(EnhancedGridIconsetTest.FILTERICON.create());

add(grid, messageDiv, horizontalLayout);

}

private List<Person> getItems() {
PersonService personService = new PersonService();
return personService.fetchAll();
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -18,9 +18,10 @@ public MainLayout() {
final RouterLink multiTree = new RouterLink("Multiple Selection Tree Grid", MultiTreeGridView.class);
final RouterLink lazySingleTree = new RouterLink("Lazy Single Selection Tree Grid", LazySingleTreeGridView.class);
final RouterLink lazyMultiTree = new RouterLink("Lazy Multiple Selection Tree Grid", LazyMultiTreeGridView.class);
final RouterLink customFilterIcon = new RouterLink("Custom filter icon grid", CustomFilterIconView.class);

final VerticalLayout menuLayout = new VerticalLayout(simpleSingleGrid, simpleMultiGrid, lazySingleGrid, lazyMultiGrid,
singleTree, multiTree, lazySingleTree, lazyMultiTree);
singleTree, multiTree, lazySingleTree, lazyMultiTree, customFilterIcon);
addToDrawer(menuLayout);
addToNavbar(drawerToggle);
}
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
package com.vaadin.componentfactory.enhancedgrid.iconset;

import com.vaadin.flow.component.dependency.JsModule;
import com.vaadin.flow.component.icon.IconFactory;
import java.util.Locale;

@JsModule("./icons/enhancedgridiconsettest.js")
public enum EnhancedGridIconsetTest implements IconFactory {

FILTERICON;

public Icon create() {
return new Icon(this.name().toLowerCase(Locale.ENGLISH).replace('_', '-').replaceAll("^-", ""));
}

public static final class Icon extends com.vaadin.flow.component.icon.Icon {
Icon(String icon) {
super("enhancedgridiconsettest", icon);
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,8 @@
import java.util.Comparator;
import java.util.Optional;

import org.apache.commons.lang3.StringUtils;

import com.vaadin.flow.component.Component;
import com.vaadin.flow.component.HasValueAndElement;
import com.vaadin.flow.component.dependency.JsModule;
Expand Down Expand Up @@ -60,6 +62,8 @@ public class EnhancedColumn<T> extends Grid.Column<T> {
private FilterField filterField;

private Component headerComponent;

private String filterIcon;

/**
* @see Column#Column(Grid, String, Renderer)
Expand Down Expand Up @@ -278,9 +282,14 @@ public String addEnhancedGridSorter(String templateInnerHtml) {
.escape(this.getInternalId());
String sortable = isSortable() ? " sortable" : "";
String filtered = hasFilterSelected() ? " filtered" : "";
return String.format(
"<enhanced-grid-sorter path='%s'" + sortable + filtered +">%s</enhanced-grid-sorter>",
escapedColumnId, templateInnerHtml);
boolean addFilterIcon = StringUtils.isNotBlank(filterIcon);
return String.format("<enhanced-grid-sorter" + (addFilterIcon ? " filtericon='" + filterIcon + "'" : "")
+ " path='%s'" + sortable + filtered + ">%s</enhanced-grid-sorter>",
escapedColumnId, templateInnerHtml);
}

protected void setFilterIcon(Icon icon) {
filterIcon = icon.getElement().getAttribute("icon");
}

/**
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,7 @@
import java.util.function.BiFunction;
import java.util.function.Predicate;

import com.vaadin.flow.component.AttachEvent;
import com.vaadin.flow.component.Component;
import com.vaadin.flow.component.ComponentEvent;
import com.vaadin.flow.component.ComponentEventListener;
Expand All @@ -42,6 +43,8 @@
import com.vaadin.flow.component.grid.Grid;
import com.vaadin.flow.component.grid.GridArrayUpdater;
import com.vaadin.flow.component.grid.GridArrayUpdater.UpdateQueueData;
import com.vaadin.flow.component.icon.Icon;
import com.vaadin.flow.component.icon.VaadinIcon;
import com.vaadin.flow.component.grid.GridSelectionModel;
import com.vaadin.flow.data.provider.ConfigurableFilterDataProvider;
import com.vaadin.flow.data.provider.DataGenerator;
Expand Down Expand Up @@ -84,6 +87,8 @@ public class EnhancedGrid<T> extends Grid<T> implements BeforeLeaveObserver, App
private SerializablePredicate<T> editablePredicate = item -> true;

private boolean showCancelEditDialog = true;

private Icon filterIcon;

SerializableFunction<T, String> selectionDisabled = new SerializableFunction<T, String>() {

Expand Down Expand Up @@ -522,5 +527,33 @@ public Registration addFilterClickedEventListener(ComponentEventListener<FilterC
return addListener(FilterClickedEvent.class, (ComponentEventListener) listener);
}

/**
* Sets an {@link Icon} to be use as the filter icon in the columns header.
* If not icon is specified it will display VaadinIcon.FILTER icon as default.
*
* @param filterIcon the icon to display as filter icon
*/
public void setFilterIcon(Icon filterIcon) {
this.filterIcon = filterIcon;
this.updateFilterIcon();
}

/**
* Updates filter icon on column's headers.
*/
private void updateFilterIcon() {
if(filterIcon != null) {
for(Column<T> column : getColumns()) {
EnhancedColumn<T> enhancedColumn = (EnhancedColumn<T>)column;
enhancedColumn.setFilterIcon(filterIcon);
}
}
}

@Override
protected void onAttach(AttachEvent attachEvent) {
super.onAttach(attachEvent);
this.updateFilterIcon();
}
}

Original file line number Diff line number Diff line change
Expand Up @@ -61,7 +61,7 @@ class EnhancedGridSorter extends GridSorter {

<slot name="direction"></slot>
<vaadin-button theme="icon" part="filter-button" role="button" path="[[path]]" on-click="_onFilterClick">
<vaadin-icon icon="vaadin:filter" slot="prefix" ></vaadin-icon>
<vaadin-icon icon="[[filtericon]]" slot="prefix" ></vaadin-icon>
</vaadin-button>
`;
}
Expand All @@ -77,7 +77,12 @@ class EnhancedGridSorter extends GridSorter {
type: Boolean,
reflectToAttribute: true,
value: false
}
},
filtericon: {
type:String,
reflectToAttribute: true,
value: "vaadin:filter"
}
};
}

Expand Down