Skip to content
This repository has been archived by the owner on Dec 12, 2022. It is now read-only.

Can't make columns resizable after adding header rows #234

Closed
pekam opened this issue Jun 18, 2018 · 16 comments
Closed

Can't make columns resizable after adding header rows #234

pekam opened this issue Jun 18, 2018 · 16 comments
Labels
Projects

Comments

@pekam
Copy link
Contributor

pekam commented Jun 18, 2018

UPDATE:
The description below seems to be incorrect. You don't need to set resizable for all the parent elements to make a column resizable. But for some reason the property/attribute doesn't seem to get updated otherwise.

Setting resizable with javascript after the grid is rendered seems to work, so as a workaround, you can use:

column.getElement().callFunction("setAttribute", "resizable", true);

Below is the old description which seems to be incorrect.


Calling column.setResizable(true) correctly sets the property for the <vaadin-grid-column>.
The problem is that the web component expects all the parent <vaadin-grid-column-groups> to have the resizable property also, or otherwise the column can't be resized. Currently we don't have a component-level API for accessing the column groups, since they are hidden behind the HeaderCell/FooterCell APIs.

One possible fix is to make sure that the parent column-groups of a resizable column always have this property also, so that the user doesn't even need to set it for the parent groups manually.

Here's a workaround which should work only after all the headers and footers are added:

private void setResizable(Column column) {
    column.setResizable(true);
    Element parent = column.getElement().getParent();
    while (parent != null
            && "vaadin-grid-column-group".equals(parent.getTag())) {
        parent.setProperty("resizable", "true");
        parent = parent.getParent();
    }
}
@pekam pekam added the bug label Jun 18, 2018
@pleku pleku added this to the 1.0 Maintenance milestone Jun 27, 2018
@DabhiGhanshyam
Copy link

Hello Pekka,

It's working with header rows.

Thanks

@DabhiGhanshyam
Copy link

DabhiGhanshyam commented Sep 5, 2018

Hello Pekka,

I have vaadin-10 grid. I did grid.prependHeaderRow() and grid.appendHeaderRow() to add 2 header rows. So now, all grid columns are re-sizable.

Now, All grid columns are joined into first header row and set it as span component to display gridn as title.

When I click on right-end side of the first header row, It gives run-time error as TypeError: Cannot read property 'offsetWidth' of undefined.

Please refers to attached screenshot.
error

I hope this clarify the scenario.

Please help.
Thanks & Regards

@pekam
Copy link
Contributor Author

pekam commented Sep 5, 2018

Hi @DabhiGhanshyam !
I couldn't reproduce the issue based on your description (tried with Chrome and Firefox). Can you give an example code snippet which definitely makes the bug occur?

@DabhiGhanshyam
Copy link

Hello Pekka,

Thanks for your quick response.

The error TypeError: Cannot read property 'offsetWidth' of undefined. occurs when I try to drag the first header row for top-right corner as attached in screen-shot.

gridresizeheaderissue

When I tried to drag that blue bar (dragging left side) at that time it throws error.

Please find code below:

`Column averagePriceColumn = vaadinGrid.addColumn(PriceData::AvgPrice).setHeader("Average Price");

HeaderRow gridFilterRow = vaadinGrid.appendHeaderRow();

Column maxPriceColumn = vaadinGrid.addColumn(PriceData::MaxPrice).setHeader("Max Price");

Span spnHeader = new Span("Price");
spnHeader.getStyle().set("font-weight", "bold");
spnHeader.getStyle().set("font-size", "16px");
spnHeader.getStyle().set("fill", "rgba(42, 71, 110, 0.6)");
spnHeader.getStyle().set("color", "rgba(42, 71, 110, 0.6)");
spnHeader.getStyle().set("margin", "auto");
spnHeader.getStyle().set("display", "table");
spnHeader.getStyle().set("font-family", "Segoe UI");

vaadinGrid.prependHeaderRow();
HeaderRow gridLableRow = vaadinGrid.getHeaderRows().get(0);
gridLableRow.join(maxPriceColumn, averagePriceColumn).setComponent(spnHeader);

vaadinGrid.getColumns().forEach(column -> {
TextField txtField = new TextField();
gridFilterRow.getCell(column).setComponent(txtField);
txtField.setSizeFull();
});
vaadinGrid.setColumnReorderingAllowed(true);

vaadinGrid.getColumns().forEach(column -> {
column.setSortable(true);
column.setResizable(true);
Element parent = column.getElement().getParent();
while (parent != null && "vaadin-grid-column-group".equals(parent.getTag())) {
parent.setProperty("resizable", "true");
parent = parent.getParent();
}
});`

Thanks once again.

@pekam
Copy link
Contributor Author

pekam commented Sep 6, 2018

Ok, I found the issue which is actually a bug in the <vaadin-grid> web component (so not in this code base which includes only the java integration for that web component). This happens whenever you have three or more resizable header rows and try to resize any cell in the third or upper header row. It doesn't matter if you have joined the cells or not.

While playing around with the client-side web component I also found out that you don't actually need to set the resizable property for all the parent elements. But for some reason the java component doesn't update the property otherwise.

Anyway, if you set resizable with javascript after the grid is already rendered, it works just by setting it for the column. So I have a simpler workaround for this now, which also avoids the bug you described:

column.getElement().callFunction("setAttribute", "resizable", true);

(Element.callFunction executes the javascript method after the grid is rendered)

Also, if you have eg. two columns, it's enough to set that for only the first column. If you set it for both, you'll get that drag-handle on the right end of the headers which doesn't make much sense.

I'll update the issue description to mention this simpler and less buggy workaround.

EDIT: Here's proof of the bug you found with just the web component:
https://glitch.com/edit/#!/friendly-hydrogen

EDIT2: Here's the issue for the web component: vaadin/vaadin-grid#1480

@DabhiGhanshyam
Copy link

Hello Pekka,

Hurray !!! Astonished !!!

It works perfectly.

Thank you very much for your great help.

@ttsanton
Copy link

ttsanton commented Mar 6, 2019

Hello,
I noticed that using the workaround of column.getElement().callFunction("setAttribute", "resizable", true); causes the resize cursor to appear on the filter row that I called with grid.appendHeaderRow() instead of on the actual first row of the Grid that I set with .setHeader(). Is there a way to keep the resize cursor on the actual headers of the grid?

Apologies in advance if I had overlooked something.

screen shot 2019-03-06 at 10 09 42 am

Code to re-create

Collator insenstiveStringComparator = Collator.getInstance();
insenstiveStringComparator.setStrength(Collator.PRIMARY);
List<Person> list = new ArrayList<>();
list.add(new Person("1", "first", "middle", "last"));
list.add(new Person("2", "Name", "Middlename", "LastName"));
ListDataProvider<Person> dataProvider = new ListDataProvider<>(list);

Grid<Person> grid = new Grid<>();
grid.addColumn(Person::getPerson_id)
	.setHeader("ID");
grid.addColumn(Person::getFirst_name)
	.setHeader("First Name")
	.setComparator((person1, person2) -> insenstiveStringComparator
		.compare(person1.getFirst_name().toLowerCase(), person2.getFirst_name().toLowerCase()))
	.setResizable(true).getElement().callFunction("setAttribute", "resizable", true);

grid.addColumn(Person::getMiddle_name)
	.setHeader("Middle Name")
	.setComparator((person1, person2) -> insenstiveStringComparator
		.compare(person1.getMiddle_name().toLowerCase(), person2.getMiddle_name().toLowerCase()))
	.getElement().callFunction("setAttribute", "resizable", true);

grid.addColumn(Person::getLast_name)
	.setHeader("Last Name")
	.setComparator((person1, person2) -> insenstiveStringComparator
		.compare(person1.getLast_name().toLowerCase(), person2.getLast_name().toLowerCase()))
	.getElement().callFunction("setAttribute", "resizable", true);

grid.setDataProvider(dataProvider);

HeaderRow filterRow = grid.appendHeaderRow();

List<ValueProvider<Person, String>> valueProviders = new ArrayList<>();
valueProviders.add(Person::getPerson_id);
valueProviders.add(Person::getFirst_name);
valueProviders.add(Person::getMiddle_name);
valueProviders.add(Person::getLast_name);

Iterator<ValueProvider<Person, String>> iterator2 = valueProviders.iterator();

grid.getColumns().forEach(column -> {
	if (iterator2.hasNext()) {
		TextField field = new TextField();
		ValueProvider<Person, String> valueProvider = iterator2.next();

		field.addValueChangeListener(event -> dataProvider.addFilter(person -> StringUtils.containsIgnoreCase(
				Normalizer.normalize(valueProvider.apply(person), Form.NFD).replaceAll("\\p{InCombiningDiacriticalMarks}+", ""),
				Normalizer.normalize(field.getValue(), Form.NFD).replaceAll("\\p{InCombiningDiacriticalMarks}+", ""))));

		field.setValueChangeMode(ValueChangeMode.EAGER);

		filterRow.getCell(column).setComponent(field);
		field.setSizeFull();
		field.setPlaceholder("Filter");
		field.addClassName("filter");
	}
});

@pekam
Copy link
Contributor Author

pekam commented Mar 7, 2019

Hi @ttsanton!
In your case, if you want the "parent"-header to be resizable, you can set the attribute on the column's parent:

column.getElement().getParent().callFunction("setAttribute", "resizable", true);

@ttsanton
Copy link

ttsanton commented Mar 7, 2019

Hi @pekam,
I seem to have some trouble using your fix of column.getElement().getParent().callFunction("setAttribute", "resizable", true); - the resize cursor will not show up when I try it out?

I tried these ways:

for (Column<Person> column : grid.getColumns()) 
	column.getElement().getParent().callFunction("setAttribute", "resizable", true);

And also

grid.addColumn(Person::getFirst_name).setHeader("First Name")
		.setComparator((person1, person2) -> insenstiveStringComparator
				.compare(person1.getFirst_name().toLowerCase(), person2.getFirst_name().toLowerCase())).getElement().getParent().callFunction("setAttribute", "resizable", true);

@pekam
Copy link
Contributor Author

pekam commented Mar 8, 2019

Sorry! I forgot to mention one important point: This needs to be done after appending the header row.

@ttsanton
Copy link

ttsanton commented Mar 8, 2019

Got it! Thank you @pekam!!!

@jtomass jtomass added this to 📬  Inbox in vaadin-core Mar 29, 2019
@KamrulHasan-Seu
Copy link

I have an Iterable list. like:
(modelRepo.findAll()) which returns the iterable list.
I can't set this list as grid items. Grid prefers the only list.
My question is how can I set iterable list?

@pekam
Copy link
Contributor Author

pekam commented Apr 16, 2019

Hi @KamrulHasan-Seu! Please ask this kind of questions next time in the Vaadin forum. This page should be reserved for discussing the particular issue described in the original post.

If your repository's return type is Iterable, then you can e.g. convert it to a List like this:

Iterable<T> items = modelRepo.findAll();
List<T> list = new ArrayList<>();
items.forEach(list::add);
grid.setItems(list);

@Haprog
Copy link

Haprog commented Jun 13, 2019

I think the main issue here is basically a duplicate of vaadin/vaadin-grid#1577 (which was just fixed in master). With the master version of the web component just setting resizable on the initial column should "work" so that you will have a working resize handle but due to the way the Java API works you would only get the resize handle on the bottom most header row.

I guess it might make sense to keep this issue still open for improving what the Java API does to manage the resizable for all layers of headers? Or should we open a new clean issue about that and close this one?

@pekam
Copy link
Contributor Author

pekam commented Jun 13, 2019

I'd consider this issue fixed if the resize-handles are working on the bottom headers after your fix.

It's a different question whether Column::setResizable should affect other header rows as well. Even if we decide that it should affect other header rows, it's not obvious whether that would be a bug fix or a breaking behavior change. Or maybe the current behavior shouldn't be touched, but new API should be added to configure resize-handles on other headers.

@Haprog
Copy link

Haprog commented Jun 14, 2019

Closing this as a duplicate of vaadin/vaadin-grid#1577 which has been fixed in vaadin-grid v5.4.4 for more info see vaadin/vaadin-grid#1577 (comment)

Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
Projects
No open projects
vaadin-core
  
📬  Inbox
Development

No branches or pull requests

6 participants