Can CssLayout be used to achieve absolute positioning of components? - vaadin

Currently I am using AbsoluteLayout, but because of some problems I would like to give CssLayout a try.
I would like to dynamically place image-, label- and button-components at specific positions in the layout.
AbsoluteLayout allows me to specify the position like so:
absoluteLayout.addComponent(component, "top:20px;left:20px")
Is something like this at all possible to achieve with CssLayout?

You can apply inline CSS for a component by overriding getCss on CssLayout, so the following should have the wanted result:
CssLayout cssLayout = new CssLayout() {
#Override
protected String getCss(Component component) {
// check the component here and return correct css. In this case only one component in the layout so this works..
return "position: relative; top: 10px; left: 10px";
}
};
cssLayout.setSizeFull();
cssLayout.addComponent(new Button("Hello"));

Related

Make Angular Material mat-select automatically take width of its selected option

How do I make automatically take width according to its selected option's width? I've looked through the API of mat-select, and was not able to find an option/input for this.
Just sharing a solution to the problem. Here's how (turn ViewEncapsulation off or prepend these selectors with ::ng-deep):
.mat-select-value {
max-width: max-content !important; // <= SOLUTION HERE...
}
.mat-form-field-infix {
width: fit-content !important; // <= and HERE...
}
Playground with this fix
My Solution is something mixed with this answer.
I took his code and modified it a bit, then in my Angular App I put the class into the styles.scss (This will be the outer most scss/css file you can find). And it works without ::ng-deep
This is my solution:
.mat-form-field-infix {
width: fit-content !important;
min-width: 200px !important;
}
This solution is not very flexible though, thats why I would suggest you calculate the width in your script and set the elements width to that. it would look something like this:
HTML:
<mat-form-field [style.width.px]="setSizeOfDropDown(16)">
Typescript:
setSizeOfDropDown(fontSize:number):number{
let width: number = minWidth; //This is so that we dont have any codesmells
return fontSize * myOptionsArr.reduce((a,b)=>{
a.length>b.length?a:b; //I used the shorthand if because it looks very clean
}).length
I multiplied the fontSize with the length of the longest string in the Array. and that is my Select width.

Cannot get #CssImport to apply only to component scope

I have been wasted hours and days trying to style the Vaadin Upload component. The goal is simple:
sometimes I need the component to show the uploaded file using its built-in file list with allows delete.
other times, I want to hide this list because I have another component such as Grid to show the file details.
Now comes the problem, I can never get it to consistently work using #CssImport with themeFor=vaadin-upload and themeFor=vaadin-upload-file. Vaadin seems to compile the shadow dom and the final result varies, it mixes up the two options and whichever comes last gets applied.
I then thought maybe because the #CssImport is in the #Route component. So, I created two custom upload components that extended the vaadin-upload component with the difference being the different #CssImport (see below). That (frustratingly) still doesn't work. I inspect the document and found that the inside the shadow-dom contains both even though I never use both on the same page.
#CssImport(value = "./css/vaadin-upload-show.css", themeFor = "vaadin-upload")
public class UploadShowFiles extends Upload {
private static final long serialVersionUID = -9198630843136885092L;
public UploadShowFiles(Receiver receiver) {
super(receiver);
}
}
#CssImport(value = "./css/vaadin-upload-hidefile.css", themeFor = "vaadin-upload")
public class UploadHideFiles extends Upload {
private static final long serialVersionUID = 2344860066834705807L;
public UploadHideFiles(Receiver receiver) {
super(receiver);
setClassName("hide-upload");
}
}
The css below will appear in the shadow dom. I expect only display: none or otherwise, not both.
[name="file-list"] {
display: none !important;
height: 0px !important;
}
[name="file-list"] div[part="file-list"] {
display: none !important;
}
[name="file-list"] {
display: block !important;
height: 1.5rem !important;
}
[name="file-list"] div[part="file-list"] {
display: block !important;
}
p/s: This is my first experience using Vaadin in a project and I probably never going to use it again. Customizing anything in Vaadin is so time-consuming and painful.
Styling in the shadow DOM can indeed be tricky. The simplified theming in Vaadin 19 helps a bit.
Where the #CssImport annotation is placed affects if the CSS should be included in the document, but not which components it affects. With themeFor, it will always be applied to all matching components.
What you can do is to use the :host selector to limit which upload components it applies to. Here I am using a class-based approach:
:host(.no-file-list) [name="file-list"] {
display: none !important;
height: 0px !important;
}
:host(.no-file-list) [name="file-list"] div[part="file-list"] {
display: none !important;
}
I can then hide the file list in an upload component by adding a class:
#Route
#CssImport(value = "./styles/upload-style.css", themeFor = "vaadin-upload")
public class FileUploadTest extends VerticalLayout {
public FileUploadTest() {
Upload uploadWithFileList = new Upload();
Upload uploadWithoutFileList = new Upload();
uploadWithoutFileList.addClassName("no-file-list");
add(uploadWithFileList, uploadWithoutFileList);
}
}

How to change the default position of button tooltips in CKEditor 5

Having a small issue with tooltips in the editor, read the api but can't understand what it is saying and I can't seem to find examples anywhere that I can understand either.
I have set up a Classic Editor build, and all the buttons on the toolbar have tooltips with the default position below the button, I want to be able, just for this one instance of the editor, to change the tooltip position to above the buttons instead. The instance is set up like this:
ClassicEditor.create( document.querySelector( '#content' ) )
.then( editor => {
console.log( 'Editor was initialized', editor );
this.annEditorInstance = editor;
} )
.catch( err => {
console.error( err.stack );
} );
That creates an editor instance that is set up exactly as I want, except for the issue with the tooltip. How do I change this? Thanks in advance.
There are two approaches to the problem:
CSS
Tooltips elements have either .ck-tooltip_s or .ck-tooltip_n class. By default all CKEditor 5 tooltips have the former so you could override it in your styles and make it act like the later:
<style>
.ck.ck-tooltip.ck-tooltip_s {
bottom: auto;
top: calc(-1 * var(--ck-tooltip-arrow-size));
transform: translateY( -100% );
}
.ck.ck-tooltip.ck-tooltip_s .ck-tooltip__text::after {
top: auto;
bottom: calc(-1 * var(--ck-tooltip-arrow-size));
transform: translateX( -50% );
border-color: var(--ck-color-tooltip-background) transparent transparent transparent;
border-width: var(--ck-tooltip-arrow-size) var(--ck-tooltip-arrow-size) 0 var(--ck-tooltip-arrow-size);
}
</style>
JS
The UI of the editor is an MVC(VM) structure. The position of the tooltip can be controlled using the JS and the Button#tooltipPosition property ('s' or 'n').
E.g. you can access the toolbar UI elements using editor.ui.view.toolbar and change their properties:
editor.ui.view.toolbar.items.map( item => item.tooltipPosition = 'n' )
but note that not all toolbar items are buttons. Some, for instance, are dropdowns so you'd need to use item.buttonView.tooltipPosition = 'n' in that case. So unless you really want to use JS, I'd go with a simple CSS solution.

How to use md-chips in line

I'm trying to use the md-chips directive of angular material in a single line, but when I add more chips than size of a field, the field add a line to bottom like in this image.
I think you need a CSS workaround to adapt the behaviour of md-chips in an input form.
For example you can use this CSS:
/* reduce input element (not visible till the user begins editing) width */
.md-chips .md-chip-input-container input {
max-width: 20px;
}
/* adapt input to md-chip height */
.myheight {
height: 49px !important;
}
/* adapt datepicker input to md-chip height */
.md-datepicker-input {
height: 49px;
}
Here is a demo: http://codepen.io/beaver71/pen/gPqPBW
P.S.: don't forget that docs declare:
Warning: This component is a WORK IN PROGRESS. If you use it now, it will probably break on you in the future.

How to use extra space after tabs in tabsheet

i am new to vaadin , i created tabsheet with two tabs one with graphs and another with some info, my problem was how to add components(combobox, labels) at right corner(same row) of the tabs.
final TabSheet tabSheet = new TabSheet();
tabSheet.setSizeFull();
tabSheet.addTab(rightAndLowerPanels, "Graphs");
tabSheet.addTab(new Label("<b>Haiiiiiiiiiiiii</b>", ContentMode.HTML), "Message");
Ex;
tab1|tab2
I want to add here
i am not able to post image for this problem.
Thanks in advance
While the component itself doesn't support this, it is possible to accomplish this with setting the components absolute position with css so it hovers over the tabsheet in the correct position.
The div(layout) that contains the tabseet and the hovering component should be set position: relative; so that the absolute position is set from the corner of the component not the browser and then set the combobox's position to something like this: position:absolute; right: 3px; top: 3px;.
You can even use Vaadin's AbsoluteLayout or CssLayout if you want to add some checks for determining the components position.
AbsoluteLayout al = new AbsoluteLayout();
al.addStyleName("tab-sheet-layout"); // position: relative;
al.addComponent(new TabSheet(new Label("1"),new Label("2")));
al.addComponent(new ComboBox(), "right: 5px; top: 5px;");
or with CssLayout:
public static class TabSheetLayout extends CssLayout {
public TabSheetLayout() {
addStyleName("tab-sheet-layout"); // position: relative;
addComponent(new TabSheet(new Label("1"),new Label("2")));
addComponent(new ComboBox());
}
#Override
protected String getCss(Component c) {
if (c instanceof ComboBox) { // do some check here
return "position:absolute; right: 3px; top: 3px;";
}
return null;
}
}
You should note however that if you resize the screen small enough, the combobox will be hovering over the tabs, so you need to stop this by fixing the layout width or by some other method.

Resources