CustomField in Vaadin 13beta1 seems to have big extra space at top - vaadin

I created a customfield that was being used in form using Vaadin 13 beta1 prerelease. However, it creates this giant blank space at the top of the field (see my green markings below, and ignore the red and yellow background colors as they were just for my understanding of what's going on.)
How can I fix this? I tried to manually set the minHeight, maxHeight, height values, but nothing changed....Here's my code for the customfield. (The code for the formlayout is fairly standard and so was not included here.)
package com.deepsearch.fe.util;
import com.vaadin.flow.component.customfield.CustomField;
import com.vaadin.flow.component.html.Label;
import com.vaadin.flow.component.orderedlayout.FlexComponent;
import com.vaadin.flow.component.orderedlayout.HorizontalLayout;
import com.vaadin.flow.component.textfield.TextField;
public class TextRangeFieldInt extends CustomField<StartToEndRangeInt> {
private final TextField start = new TextField();
private final Label lblTo = new Label("to");
private final TextField end = new TextField();
public TextRangeFieldInt(final StartToEndRangeInt startToEndRangeInt, final String startEndWidths) {
this.setHeight("10px");
this.setMinHeight("10px");
this.setMaxHeight("10px");
this.getElement().getStyle().set("background-color", "red");
//this.getStyle().set("background-color", "red");
setPresentationValue(startToEndRangeInt);
final HorizontalLayout hl = new HorizontalLayout();
hl.setWidth("100%");
hl.getStyle().set("background-color", "yellow");
hl.setMargin(false);
hl.setPadding(false);
hl.setAlignItems(FlexComponent.Alignment.CENTER);
lblTo.setWidth("1.5rem");
start.setWidth(startEndWidths);
end.setWidth(startEndWidths);
hl.add(start);
hl.add(lblTo);
hl.add(end);
add(hl);
}
#Override
protected StartToEndRangeInt generateModelValue() {
return new StartToEndRangeInt(Integer.parseInt(start.getValue()), Integer.parseInt(end.getValue()));
}
#Override
protected void setPresentationValue(StartToEndRangeInt newPresentationValue) {
start.setValue(newPresentationValue.getStartStr());
end.setValue(newPresentationValue.getEndStr());
}
}
On a different but related note, am I doing this right? There wasn't a good example yet for customfield (since it's still in beta), so I guessed that I am supposed to use a horizontal layout to add my individual components etc.
Update #1
Based on #Jouni comment below, I tried to create a much simpler formlayout which only had a few "simple" fields (eg all text fields, nothing fancy like a checkbox). But the problem remained. See screenshot below as well as the soure code for the formlayout. (Note: I even commented out the "responsiveStep" portion of the formlayout so that only default/simple scenarios were being used.)
And, here's the code snippet (it's nothing fancy):
final FormLayout nameLayout = new FormLayout();
// nameLayout.setResponsiveSteps(
// // new FormLayout.ResponsiveStep("0", 1),
//// new FormLayout.ResponsiveStep("21em", 2),
// new FormLayout.ResponsiveStep("0em", 3));
// nameLayout.add(uniqueExpName, sampleComplexity, gradientLength, numTechRepl, minMz, maxMz, enableVariableDiaWindow, densestMz, vlSampleCondit, useSettingsNextTime);
// nameLayout.add(uniqueExpName, sampleComplexity, gradientLength, numTechRepl, mzRange, enableVariableDiaWindow, densestMz, vlSampleCondit, useSettingsNextTime);
// nameLayout.add(uniqueExpName, sampleComplexity, gradientLength, numTechRepl, mzRange, enableVariableDiaWindow, densestMz, lblSampleAndConditionNumber, sampleAndCondNum);
nameLayout.add(uniqueExpName, gradientLength, numTechRepl, mzRange, densestMz);
nameLayout.setWidth("55rem");
add(nameLayout);
setAlignSelf(Alignment.CENTER, nameLayout);

The issue comes from CSS.
The default vertical alignment for inline content is baseline, which is also used by the core Vaadin layouts (including Form Layout). Baseline alignment works so that the first line of text inside an element is used for aligning that element.
In the case of Vaadin field components, that would be the label text. But, since we want to align the fields based on the field input element so that it aligns nicely with text, buttons, checkboxes, etc. on the same line (even when the field has a label and/or an error message), we have some additional CSS to move the baseline in the field elements. And apparently, this fix is missing from Custom Field.

Related

How to I get the scrollbar on the VerticalLayout rather than the HorizontalLayout in Vaadin Flow

This is using the Vaadin starter project Hello World example. In essence I want to have the scrollbar in the VerticalLayout on the left rather than on the whole page as shown in the image below:
However no matter what I do the scrollbar always appears on the right side. I suspect this may have to do with the AppLayout but I'm not sure how to adjust it so that the scrollbar is on the VerticalLayout shown in the diagram below.
The code is as follows:
add(getHelloVerticalLayout(), new HorizontalLayout(new Button("Simple")));
Where getHelloVerticalLayout() consists of just a bunch of Hello buttons so that it's large enough to generate a scrollbar on the webpage.
private VerticalLayout getHelloVerticalLayout() {
List<Button> buttons = new ArrayList<>();
for(int x=0; x<=50; x++)
buttons.add(new Button("Hello"));
return new VerticalLayout(buttons.toArray(Button[]::new));
}
You can wrap your layout, which needs a scrollbar, with the Scroller component. See the official docs for more information and example https://vaadin.com/docs/latest/ds/components/scroller

How to keep the components in the same place in FormLayout for Vaadin Flow

I would like to use FormLayout where one of the fields is visible depending on another field. Is there a way to keep the formatting the same, that is for all the fields after it to stay in their same position when another component is invisible.
Below is the code to reproduce as well as a screenshots of what I would like compared to the current behavior. In essence each time you select the combobox you make the "Year Joined Team" field invisible/visible.
TextField nameTextField = new TextField("Name");
ComboBox<String> teamComboBox = new ComboBox<>("Team");
DatePicker yearJoinedDatePicker = new DatePicker("Year Joined Team");
TextField moreFieldsTextFields = new TextField("More fields");
FormLayout formLayout = new FormLayout();
formLayout.setWidth("600px");
formLayout.setResponsiveSteps(new FormLayout.ResponsiveStep("0", 2, FormLayout.ResponsiveStep.LabelsPosition.TOP));
formLayout.add(nameTextField,
teamComboBox, yearJoinedDatePicker,
moreFieldsTextFields);
teamComboBox.setItems(List.of("One", "Two"));
teamComboBox.addValueChangeListener(change -> yearJoinedDatePicker.setVisible(!yearJoinedDatePicker.isVisible()));
formLayout.setColspan(nameTextField, 2);
add(formLayout);
Ideally the goal is to have the fields below the yearJoinedTeamDatePicker component to stay below so that all other components below continue to be aligned correctly when it's set to be invisible.
Instead what actually happens is that all the components are shifted on field to the left, as if the invisible component is no longer part of the FormLayout. Meaning the moreFieldsTextField is now on a different row, and if everything is setup for two columns every row will be incorrect. I understand that this makes sense in some context but in a FormLayout is there a way to keep the form formatted if a component is invisible?
If for example I had firstname and lastname as two side by side fields they would now be on different rows as shown below:
A very hacky solution would be to add in a Span component or something like that and make it invisible when the yearJoinedDatePicker field is visible, and invisible when it's visible. Basically fill it in with an empty field when it's invisible. That is a hacky workaround but it doesn't seem like an appropriate solution. With that in mind is there a way to keep the formatting/layout if a component is invisible?
What you are trying to achieve is sort of defying the purpose of FormLayout. FormLayout has css flex rules to wrap elements / components by row. Thus if you switch visibility of a component, the behavior is as you described.
One thing you could do, is to wrap "Team" and "Year joined team" inside e.g. HorizontalLayout and set
formLayout.setColspan(horizontalLayout, 2);
See, also my previous answer about FormLayout https://stackoverflow.com/a/69270190/8962195
If you want to keep the place, maybe it's vable for you to set the field ti disabled with setEnabled.
I'm not sure how it would behave, but you could try CSS display: none instead of the setVisibility(false).

How to recalculate column widths on scroll down(not programmatic) to a previously hidden row of a Vaadin Grid when its HeightMode is CSS

My application is similar to Vaadin Dashboard Demo (please click login after you visit this link). So all my mini dashboard items are wrapped around an abstract component that is of height 300px. One of those items is a Grid wrapped around this 300px height abstract component.
My customer hates it when he sees a large column and .v-grid-cell cuts his cell off:
text-overflow: ellipsis;
So in the #PostConstruct of my Vaadin Grid(and everywhere I mess with the container) i have
this.recalculateColumnWidths();
to alleviate my customer's concern. I tell him he can resize the column but he is not satisfied.
When my container size is small, most of the rows are visible and hence the column widths are perfect. When i have a lot of rows i have to scroll. The column widths are calculated based on the set of initially visible rows. When i scroll down, and if a newly visible row has a large column then the column gets cut off.
I can alleviate my problem by using HeightMode.ROW and make the parent Component a scrolling Panel like:
panel.setWidth("100%");
panel.setHeight("310px");
But I have a lot of action going on my Grid's FooterRow and so i don't want my user to have to scroll to the bottom to see the footers if row size is say 100. As a result my Grid has default HeightMode -> HeightMode.CSS. I like it. It always shows my HeaderRow and FooterRow and scrolls only the rows section of my Grid.
What have i tried:
Give each column humongous size or expand ratio. Customer rejected it.
I tried adding a listener for scroll event unsuccessfully. I used this similar question mentions. I could not get the scroll listener turned on.
ScrollingGrid.java:
public class ScrollingGrid extends Grid{
List<ScrollingGridScrollListener> listeners = new ArrayList<ScrollingGridScrollListener>();
private void fireSrollEvent() {
for (ScrollingGridScrollListener listener : listeners) {
listener.doGridScroll();
}
}
public void addScrollListener(ScrollingGridScrollListener listener) {
listeners.add(listener);
}
#Override
public void beforeClientResponse(boolean initial) {
super.beforeClientResponse(initial);
fireSrollEvent();
}
}`
ScrollingGridScrollListener.java:
public interface ScrollingGridScrollListener {
public void doGridScroll();
}
and in my Grid:
addScrollListener(this);
and
#Override
public void doGridScroll() {
Notification.show("You are scrolling!\nYou can add your own behavior here!");
this.recalculateColumnWidths();
}
I see the notification when page loads. Maybe i should not override beforeClientResponse method in Grid. But I don't know what method to override to achieve a scroll listener.
Help me figure out this scroll listener or if there is another way i can get recalculated column widths on scroll, please let me know.
Thanks for reading this very long question.
Version: 7.6.8

Vaadin Grid custom TextArea editor is not being fully shown

I have defined a custom editor for my Vaadin 7 Grid
longColumn.setEditorField(getTextArea());
where getTextArea() is:
private Field<?> getTextArea() {
TextArea ta=new TextArea();
ta.setWidth("300px");
ta.setHeight("200px");
return ta;
}
The TextArea appears to be of the given size, but it is cut to the height of the row, and is completely unusable.
Is there any way to make the editor to be bigger in order to use a TextArea that big?
Add a custom height via CSS by adding a new style using setRowStyleGenerator() to the Grid.

Setting padding in a blackberry app

I'm trying to set the padding between various fields in a blackberry app. I can use setpadding method but this seems like overkill for what im trying to achieve. I just want to set a consistent spacing around all fields. Is this possbible without using setpadding? My fields are part of a verticalfield managers if that helps.
Thanks
If these are Fields you will be using frequently with the same amount of spacing the easiest solution would probably to extend the Field and in the constructor call a setMargin() on it.
public class SpacedLabelField extends LabelField {
public SpacedLabelField(String text, long style) {
super(text, style);
setMargin(10, 10, 10, 10);
}
}
I would recommend setMargin() because the Managers will take that information and give you an even spacing. For example, you have Field A with a bottom margin of 10 and Field B with a top margin of 10. If you stack A on top of B you will end up with a spacing between them of 10 rather than 20 (at least this has been my observed behavior in 5.0).
At any rate, now rather than having to create your Field and then call setMargin() on each, you only have to call your class and it will already be formatted for you.
Alternatively you could create your own Manager and in the sublayout() call implement a spacing between the Field when you are laying out and positioning them.

Resources