-
Notifications
You must be signed in to change notification settings - Fork 67
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
feat: Flow integration for Grid's cell-focus event (#822)
Fixes: vaadin/vaadin-grid#1536 Extended grid connector to handle the client side cell-focus event, integrated the grid event context and added a CellFocusEvent class and respective listener to Grid. Co-authored-by: Sascha Ißbrücker <[email protected]> Co-authored-by: Tulio Garcia <[email protected]>
- Loading branch information
1 parent
0bb8758
commit 0deb0b6
Showing
5 changed files
with
427 additions
and
0 deletions.
There are no files selected for viewing
92 changes: 92 additions & 0 deletions
92
...-integration-tests/src/main/java/com/vaadin/flow/component/grid/it/GridCellFocusPage.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,92 @@ | ||
/* | ||
* Copyright 2000-2021 Vaadin Ltd. | ||
* | ||
* Licensed under the Apache License, Version 2.0 (the "License"); you may not | ||
* use this file except in compliance with the License. You may obtain a copy of | ||
* the License at | ||
* | ||
* http://www.apache.org/licenses/LICENSE-2.0 | ||
* | ||
* Unless required by applicable law or agreed to in writing, software | ||
* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT | ||
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the | ||
* License for the specific language governing permissions and limitations under | ||
* the License. | ||
*/ | ||
package com.vaadin.flow.component.grid.it; | ||
|
||
import com.vaadin.flow.component.grid.Grid; | ||
import com.vaadin.flow.component.grid.Grid.Column; | ||
import com.vaadin.flow.component.html.Div; | ||
import com.vaadin.flow.component.html.Span; | ||
import com.vaadin.flow.router.Route; | ||
|
||
/** | ||
* Page created for testing purposes. Not suitable for demos. | ||
* | ||
* @author Vaadin Ltd. | ||
*/ | ||
@Route("vaadin-grid/grid-cell-focus-page") | ||
public class GridCellFocusPage extends Div { | ||
|
||
public static final String ID_GRID = "cell-focus-grid"; | ||
public static final String ID_ITEM_RESULT = "cell-focus-item-result"; | ||
public static final String ID_COLUMN_RESULT = "cell-focus-column-result"; | ||
public static final String ID_SECTION_RESULT = "cell-focus-section-result"; | ||
|
||
public static final String KEY_FIRST_COLUMN = "first-column"; | ||
public static final String KEY_SECOND_COLUMN = "second-column"; | ||
public static final String KEY_THIRD_COLUMN = "third-column"; | ||
|
||
public static final String NO_ITEM = "-- no item --"; | ||
public static final String NO_COLUMN = "-- no column --"; | ||
public static final String NO_SECTION = "-- no section --"; | ||
|
||
public GridCellFocusPage() { | ||
setSizeFull(); | ||
|
||
Grid<String> grid = new Grid<>(); | ||
grid.setId(ID_GRID); | ||
|
||
grid.addColumn(s -> s + "1") | ||
.setKey(KEY_FIRST_COLUMN) | ||
.setHeader("First column header") | ||
.setFooter("First column footer"); | ||
grid.addColumn(s -> s + "2") | ||
.setKey(KEY_SECOND_COLUMN) | ||
.setHeader("Second column header") | ||
.setFooter("Second column footer"); | ||
grid.addColumn(s -> s + "3") | ||
.setKey(KEY_THIRD_COLUMN) | ||
.setHeader("Third column header") | ||
.setFooter("Third column footer"); | ||
|
||
grid.setItems("A", "B", "C", "D"); | ||
|
||
Span itemResult = new Span(); | ||
itemResult.setId(ID_ITEM_RESULT); | ||
|
||
Span colResult = new Span(); | ||
colResult.setId(ID_COLUMN_RESULT); | ||
|
||
Span sectionResult = new Span(); | ||
sectionResult.setId(ID_SECTION_RESULT); | ||
|
||
add(itemResult, colResult, sectionResult, grid); | ||
|
||
grid.addCellFocusListener(event -> { | ||
String item = event | ||
.getItem() | ||
.orElse(NO_ITEM); | ||
|
||
String column = event | ||
.getColumn() | ||
.map(Column::getKey) | ||
.orElse(NO_COLUMN); | ||
|
||
itemResult.setText(item); | ||
colResult.setText(column); | ||
sectionResult.setText(event.getSection().getClientSideName()); | ||
}); | ||
} | ||
} |
114 changes: 114 additions & 0 deletions
114
...ntegration-tests/src/test/java/com/vaadin/flow/component/grid/it/GridCellFocusPageIT.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,114 @@ | ||
/* | ||
* Copyright 2000-2021 Vaadin Ltd. | ||
* | ||
* Licensed under the Apache License, Version 2.0 (the "License"); you may not | ||
* use this file except in compliance with the License. You may obtain a copy of | ||
* the License at | ||
* | ||
* http://www.apache.org/licenses/LICENSE-2.0 | ||
* | ||
* Unless required by applicable law or agreed to in writing, software | ||
* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT | ||
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the | ||
* License for the specific language governing permissions and limitations under | ||
* the License. | ||
*/ | ||
package com.vaadin.flow.component.grid.it; | ||
|
||
import org.junit.Assert; | ||
import org.junit.Test; | ||
|
||
import com.vaadin.flow.component.grid.CellFocusEvent; | ||
import com.vaadin.flow.component.grid.testbench.GridElement; | ||
import com.vaadin.flow.testutil.TestPath; | ||
import com.vaadin.testbench.TestBenchElement; | ||
import com.vaadin.tests.AbstractComponentIT; | ||
|
||
/** | ||
* IT for grid's Flow based cell focus event. | ||
* | ||
* @author Vaadin Ltd | ||
*/ | ||
@TestPath("vaadin-grid/grid-cell-focus-page") | ||
public class GridCellFocusPageIT extends AbstractComponentIT { | ||
|
||
@Test | ||
public void focusBodyCell() { | ||
open(); | ||
|
||
getGrid().getCell(0, 0).focus(); | ||
assertTextResult(GridCellFocusPage.ID_ITEM_RESULT, "A"); | ||
assertTextResult(GridCellFocusPage.ID_COLUMN_RESULT, | ||
GridCellFocusPage.KEY_FIRST_COLUMN); | ||
assertTextResult(GridCellFocusPage.ID_SECTION_RESULT, | ||
CellFocusEvent.GridSection.BODY.getClientSideName()); | ||
|
||
getGrid().getCell(1, 0).focus(); | ||
assertTextResult(GridCellFocusPage.ID_ITEM_RESULT, "B"); | ||
assertTextResult(GridCellFocusPage.ID_COLUMN_RESULT, | ||
GridCellFocusPage.KEY_FIRST_COLUMN); | ||
assertTextResult(GridCellFocusPage.ID_SECTION_RESULT, | ||
CellFocusEvent.GridSection.BODY.getClientSideName()); | ||
|
||
getGrid().getCell(2, 1).focus(); | ||
assertTextResult(GridCellFocusPage.ID_ITEM_RESULT, "C"); | ||
assertTextResult(GridCellFocusPage.ID_COLUMN_RESULT, | ||
GridCellFocusPage.KEY_SECOND_COLUMN); | ||
assertTextResult(GridCellFocusPage.ID_SECTION_RESULT, | ||
CellFocusEvent.GridSection.BODY.getClientSideName()); | ||
} | ||
|
||
@Test | ||
public void focusHeaderCell() { | ||
open(); | ||
|
||
getGrid().getHeaderCell(0).focus(); | ||
assertTextResult(GridCellFocusPage.ID_ITEM_RESULT, | ||
GridCellFocusPage.NO_ITEM); | ||
assertTextResult(GridCellFocusPage.ID_COLUMN_RESULT, | ||
GridCellFocusPage.KEY_FIRST_COLUMN); | ||
assertTextResult(GridCellFocusPage.ID_SECTION_RESULT, | ||
CellFocusEvent.GridSection.HEADER.getClientSideName()); | ||
|
||
getGrid().getHeaderCell(1).focus(); | ||
assertTextResult(GridCellFocusPage.ID_ITEM_RESULT, | ||
GridCellFocusPage.NO_ITEM); | ||
assertTextResult(GridCellFocusPage.ID_COLUMN_RESULT, | ||
GridCellFocusPage.KEY_SECOND_COLUMN); | ||
assertTextResult(GridCellFocusPage.ID_SECTION_RESULT, | ||
CellFocusEvent.GridSection.HEADER.getClientSideName()); | ||
} | ||
|
||
@Test | ||
public void focusFooterCell() { | ||
open(); | ||
|
||
getGrid().getFooterCell(0).focus(); | ||
assertTextResult(GridCellFocusPage.ID_ITEM_RESULT, | ||
GridCellFocusPage.NO_ITEM); | ||
assertTextResult(GridCellFocusPage.ID_COLUMN_RESULT, | ||
GridCellFocusPage.KEY_FIRST_COLUMN); | ||
assertTextResult(GridCellFocusPage.ID_SECTION_RESULT, | ||
CellFocusEvent.GridSection.FOOTER.getClientSideName()); | ||
|
||
getGrid().getFooterCell(1).focus(); | ||
assertTextResult(GridCellFocusPage.ID_ITEM_RESULT, | ||
GridCellFocusPage.NO_ITEM); | ||
assertTextResult(GridCellFocusPage.ID_COLUMN_RESULT, | ||
GridCellFocusPage.KEY_SECOND_COLUMN); | ||
assertTextResult(GridCellFocusPage.ID_SECTION_RESULT, | ||
CellFocusEvent.GridSection.FOOTER.getClientSideName()); | ||
} | ||
|
||
private GridElement getGrid() { | ||
return $(GridElement.class).id(GridCellFocusPage.ID_GRID); | ||
} | ||
|
||
private void assertTextResult(String resultFieldId, String expectedResult) { | ||
String text = $(TestBenchElement.class) | ||
.id(resultFieldId) | ||
.getText(); | ||
|
||
Assert.assertEquals(expectedResult, text); | ||
} | ||
} |
166 changes: 166 additions & 0 deletions
166
...-parent/vaadin-grid-flow/src/main/java/com/vaadin/flow/component/grid/CellFocusEvent.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,166 @@ | ||
/* | ||
* Copyright 2000-2021 Vaadin Ltd. | ||
* | ||
* Licensed under the Apache License, Version 2.0 (the "License"); you may not | ||
* use this file except in compliance with the License. You may obtain a copy of | ||
* the License at | ||
* | ||
* http://www.apache.org/licenses/LICENSE-2.0 | ||
* | ||
* Unless required by applicable law or agreed to in writing, software | ||
* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT | ||
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the | ||
* License for the specific language governing permissions and limitations under | ||
* the License. | ||
*/ | ||
package com.vaadin.flow.component.grid; | ||
|
||
import java.util.Objects; | ||
import java.util.Optional; | ||
|
||
import com.vaadin.flow.component.ComponentEvent; | ||
import com.vaadin.flow.component.DomEvent; | ||
import com.vaadin.flow.component.EventData; | ||
|
||
/** | ||
* Event fired when a cell in the Grid is focused. | ||
* | ||
* @param <T> the grid bean type | ||
* @author Vaadin Ltd | ||
* <p> | ||
* @see Grid#addCellFocusListener(com.vaadin.flow.component.ComponentEventListener) | ||
*/ | ||
@DomEvent("grid-cell-focus") | ||
public class CellFocusEvent<T> extends ComponentEvent<Grid<T>> { | ||
|
||
private final transient T item; | ||
private final Grid.Column<T> column; | ||
private final GridSection section; | ||
|
||
/** | ||
* Creates a new cell focus event. | ||
* | ||
* @param source the source component | ||
* @param fromClient <code>true</code> if the event originated from the | ||
* client | ||
*/ | ||
public CellFocusEvent(Grid<T> source, boolean fromClient, | ||
@EventData("event.detail.itemKey") String itemKey, | ||
@EventData("event.detail.internalColumnId") | ||
String internalColumnId, | ||
@EventData("event.detail.section") String sectionName) { | ||
super(source, fromClient); | ||
|
||
item = source.getDataCommunicator().getKeyMapper().get(itemKey); | ||
column = source.getColumnByInternalId(internalColumnId); | ||
section = GridSection.ofClientSideName(sectionName); | ||
} | ||
|
||
/** | ||
* Indicates, if the clicked cell is part of the grid's body section. | ||
* | ||
* @return is a body cell | ||
*/ | ||
public boolean isBodyCell() { | ||
return section == GridSection.BODY; | ||
} | ||
|
||
/** | ||
* Indicates, if the clicked cell is part of the grid's header section. | ||
* | ||
* @return is a header cell | ||
*/ | ||
public boolean isHeaderCell() { | ||
return section == GridSection.HEADER; | ||
} | ||
|
||
/** | ||
* Indicates, if the clicked cell is part of the grid's footer section. | ||
* | ||
* @return is a footer cell | ||
*/ | ||
public boolean isFooterCell() { | ||
return section == GridSection.FOOTER; | ||
} | ||
|
||
/** | ||
* Returns the grid section, where this cell is located. Never null. | ||
* @return section | ||
*/ | ||
public GridSection getSection() { | ||
return section; | ||
} | ||
|
||
/** | ||
* Returns the item represented by the focused cell. Is empty, when the | ||
* focused cell is not a body cell. | ||
* | ||
* @return item or empty | ||
*/ | ||
public Optional<T> getItem() { | ||
return Optional.ofNullable(item); | ||
} | ||
|
||
/** | ||
* Returns the column represented by the focused cell. Is empty, when the | ||
* focused cell is a header group (a | ||
* cell with a cellspan > 1). | ||
* | ||
* @return column or empty | ||
*/ | ||
public Optional<Grid.Column<T>> getColumn() { | ||
return Optional.ofNullable(column); | ||
} | ||
|
||
/** | ||
* An enum representing the different sections of a grid. | ||
*/ | ||
public enum GridSection { | ||
/** | ||
* Header section. | ||
*/ | ||
HEADER("header"), | ||
|
||
/** | ||
* Body section. | ||
*/ | ||
BODY("body"), | ||
|
||
/** | ||
* Footer section. | ||
*/ | ||
FOOTER("footer"); | ||
|
||
|
||
private final String clientSideName; | ||
|
||
GridSection(String clientSideName) { | ||
this.clientSideName = clientSideName; | ||
} | ||
|
||
/** | ||
* Returns the matching {@link GridSection} for the given client side name. | ||
* An unknown client side name will lead to an exception. | ||
* @param clientSideName client side name to lookup | ||
* @throws IllegalArgumentException on an unknown client side section name | ||
* @return matching section instance | ||
*/ | ||
public static GridSection ofClientSideName(String clientSideName) { | ||
for (GridSection section : values()) { | ||
if (Objects.equals(clientSideName, section.getClientSideName())) { | ||
return section; | ||
} | ||
} | ||
|
||
throw new IllegalArgumentException("Unknown section client side section name: " + clientSideName); | ||
} | ||
|
||
/** | ||
* Returns the client side name of the section. | ||
* @return client side name | ||
*/ | ||
public String getClientSideName() { | ||
return clientSideName; | ||
} | ||
} | ||
} |
Oops, something went wrong.