miércoles, 9 de septiembre de 2020

33. Detecting and solving problems Vaadin 16.0.3 and 17.0.1

 1. Incompatible pnpm versions

Vaadin wants pnpm versions in a determinate range. So DO NOT install pnpm. Vaadin will install it for you.


2.  pnpm fails when downloading resources

2.1 See previous error (1)

2.2 Delete these files from the main folder of the project:

- package.json

pnpmfile.js

- pnpm-lock.yaml

- {}tsconfig.json

- types.d.ts

- webpack.config.js

- webpack.generated.js

- mode_modules (folder)


2.3 reset the project as follows: 

2.3.1 Select the parent project and Run As - Maven Clean

2.3.2 Select the parent project and Maven - Update Project

2.3.3 Select the parent project and Run As - Maven Build .. - and goals: "clean package" and profiles: "production"

2.3.4. Select the vaadin (child) project and Run As - Maven Clean

2.3.5 Select the  vaadin (child) project and Maven - Update Project (select all the project that is a dependant)


3.  Errors in some json files in the node_modules folder

These errors are causes by comments and duplicate assignments of parameters.

Modify these files and remove commends and duplicated assignments


4.  Java 14.!!!!

There can be some problems in Eclipse using Java 14+. see My Spanish blog Informatica Dantesca.

5.  @Push annotation and Vaadin 17.0.x

The @Push annotation does not work still in Vaadin 17.0.1 unless you use it in the appropriate class. It is a problem with new versions. It should be used in another class. See the previous post

sábado, 16 de mayo de 2020

32. Vaadin 15. New version. Using pnpm instead of npm

1. Introduction
Vaadin proposes to user pnpm instead of npm as it seems quicker and saves disk space.

To achieve this goal one can use several ways, see Vaadin 15 for complete details:
  1. In Spring: in the application.properties file, set this property vaadin.pnpm.enable=true
  2. In a plain JEE application with the @WebServlet annotation (is the one I use)
  3. In a plain JEE application by means of the web.xml file
  4. In the pom.xml file, in the part of the vaadin-maven-plugin

My option is using the @WebServlet annotation, as in my project, I used this class to define the management of internationalization and CDI. Here is the source code


 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
package openadmin.listeners;

import javax.servlet.annotation.WebInitParam;
import javax.servlet.annotation.WebServlet;

import com.vaadin.cdi.CdiVaadinServlet;
import com.vaadin.flow.server.Constants;

/**
 * Information about app servlet 
 * 
 * Necessary for defining i18n Provider
 * @author ximo 
 *
 */
@SuppressWarnings("serial")
@WebServlet(
	urlPatterns = "/*", 
	name = "slot", 
	asyncSupported = true, 
	initParams = {
		
	// I18N Provider for translation of labels	
        @WebInitParam(name = Constants.I18N_PROVIDER, value = "openadmin.i18n.MyI18nProvider"),
        
        // Enable pmpm instead of npm	
        @WebInitParam(name = "pnpm.enable", value = "true")
 	})


public class ApplicationServlet extends CdiVaadinServlet {
}
  

martes, 21 de abril de 2020

31. Vaadin 14. Integrating external Js libraries from npm (3). Apexcharts

0. Introduction

Please read this previous post to get more details. I have tested this code with Vaadin 15 and it works!

Let's use the magnific library "apexcharts" .

Steps:
  1. Create a folder in the frontend called for instance "apex-charts".
  2. Create a file for instance "apex-charts-test.js" into the previous folder.
  3. Create a class that can contain other Html elements (like a Div) that will contain the chart.  


1. apex-charts-tests.js

Line 1: Import the required dependencies.
Line 5: A function for rendering a chart. The parameters are:
  • jsElem that is a representation of the right-hand assignment of a javascript variable that will contain the graph definition. In the apexchart web is an example that is used here. The value is defined in line 3 of the Main component that will display the component inside. and is a right-hand assignment of a variable in javascript (last source code of the post)
  • divId: the id of an Html element that will contain the char object.
Line 7: Construct a javascript sentence for evaluating the chart definition. In the next sentence is evaluated and the variable myCharDef is assigned the value of the chart.

Line 9: Retrieve the Html element whose id is the one defined in the variable divId.
Line10. Creates the chart object and in the next line is rendered into the Html element.

Line 15. The function is assigned to the window object so that it gets global presence and can be called from a Vaadin component.

Here is the code

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
import ApexCharts from "apexcharts";

class ApexChartsEdu  {
 
 render(jsElem, divId) {
  var myCharDef={};
  var kk="myCharDef="+jsElem;
  eval(kk);
  var aDiv=document.querySelector("#"+divId);
  this.chart=new ApexCharts(aDiv, myCharDef);
  this.chart.render();
 }
}

window.renderApexChart = function (jsValue, anId) {
 const mychart= new ApexChartsEdu();
 mychart.render(jsValue, anId);
}

2. The ApexChart class

Line 8: Import the "apex-charts-test.js"  referenced from the frontend folder
Line 9: Import the library from the npn repository.
Line 15: Constructor that requires the id of the div component so that it will be accesible from the javascript function
Line 20: Renders the chart with the  jsString definition.


 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
package openadmin.ui.forms.elements.customform.apexcharts;

import com.vaadin.flow.component.dependency.JsModule;
import com.vaadin.flow.component.dependency.NpmPackage;
import com.vaadin.flow.component.html.Div;

@SuppressWarnings("serial")
@JsModule("./apex-charts/apex-charts-test.js")
@NpmPackage(value = "apexcharts", version = "3.18.1")

public class ApexCharts extends Div{

 private String myId="";
 
 public ApexCharts(String myId) {
  this.myId=myId;
  this.setId(myId);
    }
 
 public void render(String jsString) {
  System.out.println("myId="+ myId);
  getElement().executeJs("window.renderApexChart($0, $1)", jsString, myId);
 }
}


3. Creating a chart and inserting it into a component (Main)

Line 1: Create the Div component that will contain the chart
Line 2: add the component to the main component
Line 3: Define the right-hand assignment of the definition of the char
Line 16: rendering the component.


 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
ApexCharts apex= new ApexCharts("mysuperdiv");
add(apex);
String jsStuff="{" + 
  "  chart: {" + 
  "    type: 'line'" + 
  "  }," + 
  "  series: [{" + 
  "    name: 'sales'," + 
  "    data: [30,40,35,50,49,60,70,91,125]" + 
  "  }]," + 
  "  xaxis: {" + 
  "    categories: [1991,1992,1993,1994,1995,1996,1997, 1998,1999]" + 
  "  }" + 
  "}";
  
apex.render(jsStuff);




jueves, 9 de abril de 2020

30. Vaadin 14. Integrating external Js libraries from npm (2). TinyMce. NOT WORKING!!!!!

0. Introduction

Now that I have tried to use TinyMce in my Vaadin projects, but integrating with Vaadin 14 is rather difficult because the component tries to find themes and skins and cannot find them. This maybe can be due to the shadow dom, which can encapsulate most of the code so that variables and paths get local and cannot be accessed.

The main ideas of this post are from the Vaadin forum.

The steps to follow are:

1. Create a js file to get the function tinymce.init() global so that it can be accessed by the Vaadin component. this file will be put in the frontend folder. Remember that to make a function global, it should be incorporated into the "window" object.
2. Create the component class with the @NpmPackage annotation to import the tinymce module from npm
3. Execute the build process so that the npm_modules folder will be filled with the npm dependencies. If you, instead of executing the build process, execute Run As-> Run on server, then you will get an error that cannot find the "./tinymceEdu/themes/silver.index.js". To solve this error, you should comment the line 18 that tries to import this module by means of the @JsModule annotation.
4. Copy the folder npm_modules/tinymce/skins to src/main/webapp folder and we will get the folder src/main/webapp/skins.
5. Create a folder "tinymceEdu" (or any other name different from "tinymce") in the folder frontend.
6. Copy the folder npm_modules/tinymce/themes to the last folder, getting frontend/tinymceEdu/themes folder
7. Create the main form and include this component

1. The js file

I have called it tinymce-test.js . It will be placed in the "frontend" folder


1
2
3
4
5
import * as TINY from "tinymce";

window.initTinymce = function() {
 tinymce.init({selector:'textarea'});
}


2. The component class



 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
package com.gmail.ximo;
import java.util.UUID;
import com.vaadin.flow.component.AttachEvent;
import com.vaadin.flow.component.Tag;
import com.vaadin.flow.component.customfield.CustomField;
import com.vaadin.flow.component.dependency.JsModule;
import com.vaadin.flow.component.dependency.NpmPackage;

@SuppressWarnings("serial")

//Our js file used to make the library functions global
@JsModule("./tinymce-test.js") // New! [1]

//Theme
@JsModule("./tinymceEdu/themes/silver/index.js") // Modified! [2]

//Npm
@NpmPackage(value = "tinymce", version = "5.2.1") // Modified! [3]
@Tag("textarea")
public class TinyMce extends CustomField<String> {
    public TinyMce(){
        this.setId(UUID.randomUUID().toString());
    }

    @Override
    protected String generateModelValue() {
        return getElement().getText();
    }

    @Override
    protected void setPresentationValue(String s) {
        getElement().setText(s);
    }

    @Override
    protected void onAttach(AttachEvent attachEvent) {
        super.onAttach(attachEvent);
        this.getElement().executeJs("window.initTinymce()"); //Modified [4]
        this.setWidth("500px"); // Modified [5]
    }
}

Line 12: references the file" tinymce-text.js" so that we can use the "window.initTinymce()" function declared in this js file. The execution of this function is in line  38.

Line 15: references the copied folder themes from npm_modules/tinymce/themes to frontend/tinymceEdu/themes

Line 18: the reference to the tinymce package from the npm repository

Line 19: the tag used in html

Line 38: The use of the function tinymce.init() which has been "globalized" in the "tinymce-test.js" file passing it to the window object


3. The main view class

Here is the simple code


 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
package com.gmail.ximo;

import com.vaadin.flow.component.orderedlayout.VerticalLayout;
import com.vaadin.flow.router.Route;
import com.vaadin.flow.server.PWA;
import javax.annotation.PostConstruct;


/**
 * The main view contains a simple label element and a template element.
 */
@SuppressWarnings("serial")
@Route("")
@PWA(name = "Project Base for Vaadin Flow with CDI", shortName = "Project Base")
public class MainView1 extends VerticalLayout {

    @PostConstruct
    public void init() {
        TinyMce tiny= new TinyMce(); 
        add(tiny);
    }
}

Now you can run it (if you use the start-up project from Vaadin as Run As- Maven Build.. - Goals : "clean package tomee:run" or Run -Run on Server ... if you are using Tomcat server and have configured the pom.xml as in this post).



Happy coding!

29. Vaadin 14. Integrating external Js libraries from npm (1). Playing a note with Tone.js

0. Introduction

This post is based on a contribution to Vaadin form by Arthur Signell. This is a very important and useful contribution.

The steps for achieving these aims are:
  1. Create a js file (in the frontend folder) that defines the calls to the js library. 
  2. Create a java file that imports the js library from the npm and execute the functions of the previously created js file

1. JS important tips

1. Nearly all the variables and functions created are local! That means that they cannot be used in a Vaadin Java class. For instance variable "a" and function "myfunct" are local:
  
     var a = 5; 
     myfunc ( c, d) { return c + d; }
  
2. If you want a variable or function that can be recognized by a Vaadin component, (that means to make them global), you must attach it to window object. For instance  variable "b" and function "otherfunct" are global:

    window.b = 5;
    window.otherfunct= function ( c, d) { return c + d; }

3. If you want to make an "import" of the external javascript library for instance:

    import * as TONE from "tone";
 
  The reference to the external javascript library must be made by means of @NpmPackage  annotation in the Vaadin component class that uses it:

   @NpmPackage (value = "tone", version = "13.8.25")

Here we are importing the library "tone.js" version "13.8.25" from the npm repository

4. To reference the created js file from the Vaadin Component class, the @JsModule annotation can be used:
 
   @JsModule("./tone-test.js")

2. Create the js file

This simple file makes visible (global) the variables and functions we need to use and call from our Vaadin component.

This file must be in the "frontend" folder!. 

Here is a file ( tone-test.js )  that plays a note with a specific duration using tone.jshttps://tonejs.github.io/ library 


 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
import * as TONE from "tone";

class ToneTest {
 //Create the synthesizer
 init() {
  this.synth = new TONE.Synth().toMaster();
 }
 
 // Play notes
 play(note, duration) {
  this.synth.triggerAttackRelease(note, duration)
 }  
}  

//Make the functions global

//Create the synthesizer
window.initTone = function() {
 window.tt = new ToneTest(); //makes the variable global
 window.tt.init();
}

// Play the notes
window.play = function (note,duration) {
 window.tt.play(note,duration);
}

Now it is possible to call the functions "window.initTone" and "window.play" as they are attached to the window that is a global object (Lines 18 and 24)

Don't forget to make the imports (Line 1)

There is an intermediate class (ToneTest)  for managing direct calls to tone.js functions (Lines 3-13)


3. The Vaadin Component Class

It is important to note:
  1.  Line 21: the @NpmPackage annotation for importing the library tone.js version 13.8.25 from npm
  2. Line 20: The @JsModule that import the previous "tone-test.js" javascript file that was saved in the frontend folder. If we had saved it in an inner folder of the frontend folder, for instance, frontend/tone the annotation would have been @JsModule("./tone/tone-test.js")
  3. Line 28: In the init() method annotated as PostConstruct, we make sure to initialize the synthesizer. To execute a js code the getElement().executeJs(function,parameters...) is used.
  4. Line 32: The click event of the button is assigned to the js call to play a "C4" note for a duration of an 8th of a whole note.

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
package com.gmail.ximo;

import com.vaadin.flow.component.Key;
import com.vaadin.flow.component.button.Button;
import com.vaadin.flow.component.dependency.JsModule;
import com.vaadin.flow.component.dependency.NpmPackage;
import com.vaadin.flow.component.orderedlayout.VerticalLayout;
import com.vaadin.flow.router.Route;
import com.vaadin.flow.server.PWA;

import javax.annotation.PostConstruct;
import javax.inject.Inject;

/**
 * The main view contains a simple label element and a template element.
 */
@SuppressWarnings("serial")
@Route("")
@PWA(name = "Project Base for Vaadin Flow with CDI", shortName = "Project Base")
@JsModule("./tone-test.js")
@NpmPackage(value = "tone", version = "13.8.25")
public class MainView extends VerticalLayout {


    @PostConstruct
    public void init() {
        //Initialize the synthesizer        
        this.getElement().executeJs("window.initTone()");

        // Play a C4 Note with a duration of a 8th
        Button button = new Button("Say hello",
            e -> getElement().executeJs("window.play($0,$1)", "C4", "8n"));
        // You can specify keyboard shortcuts for buttons.
        // Example: Pressing enter in this view clicks the Button.
        button.addClickShortcut(Key.ENTER);

        add(button);
    }

}

I hope you have a good time!

jueves, 6 de febrero de 2020

28. Vaadin 14. How to display programmatically components to the OpenXava (C) way

1. Introduction

OpenXava is a wonderful framework based on the Model. I love it. I am a fan of its creator Mr. Javier Paniza. He has designed a nomenclature for defining the "view" part of an MVC pattern. As he states, programmers can devote to business logic instead of designing complicated HTML, CSS or javascript code on the client-side.
Now responsiveness is a must.

Vaadin has a Horizontal and a Vertical  Layout component, that seems responsive, but when you nest them it is very difficult for me to keep track of the CSS code added by Vaadin Themes.. so you cannot predict how the information is displayed

After struggling about for some days and googling some days too, I found the CSS flex property

Another problem is that you cannot know the real width and height of the components in run time, you should use some unpredictable javascript code that is not recommended.

2. Designing the layout


A simple definition of a view in OpenXava could be:
--------------------------------------------------------------------------------------------------------------------
student   [ firstName,    lastName;
            address       [streetName, number, city ],
            parents       [mother,     father]
          ];
Sports    [ firstSport;   secondSport]
--------------------------------------------------------------------------------------------------------------------

That should produce something like this:

+------------------------------------------------------------------------------+
| +--------------------------------------------------------------------------+ |
| |                                  Student                                 | |
| +--------------------------------------------------------------------------+ |
| |             +-------------+             +-------------+                  | |
| | First Name: |             Last Name: |             |                  | |
| |             +-------------+             +-------------+                  | | 
| | +---------------------------------------+ +----------------------------+ | | 
| | |            Address                    | |          Parents           | | |
| | +---------------------------------------+ +----------------------------+ | |
| | |        +------+    +---+       +----+ | |     +------+      +------+ | | |
| | | Street:|      | N. |   | City: |    | | | Mom:|      | Dad: |      | | | |
| | |        +------+    +---+       +----+ | |     +------+      +------+ | | |
| | +---------------------------------------+ +----------------------------+ | |
| |                                                                          | |
| +--------------------------------------------------------------------------+ |
| |                              Sports                                      | |
| +--------------------------------------------------------------------------+ |
| | |                +----------------------------------------+              | |
| | |  First Sport:  |                                        |              | |
| | |                +----------------------------------------+              | |
| | |                +----------------------------------------+              | |
| | |  Second Sport: |                                        |              | |
| | |                +----------------------------------------+              | |
| +--------------------------------------------------------------------------+ |
+------------------------------------------------------------------------------+



Now to simplify I will be using this pseudo Html structure:

Main form: (Horizontal Panel)
   |
   +--> Vertical Panel
        |
        +--> Horizontal Panel (Student)
        |    |
        |    +--> Vertical Panel
        |         |
        |         +--> Horizontal Panel (line of controls)
        |         |    |
        |         |    +--> Field (First Name)
        |         |    |
        |         |    +--> Field (Last Name)
        |         |     
        |         +--> Horizonal Panel  
        |              |
        |              +--> Vertical Panel
        |                   |
        |                   +--> Horizontal Panel (Address)
        |                   |    |
        |                   |    +--> Vertical Panel 
        |                   |        |   
        |                   |        +--> Horizontal Panel (line of controls)
        |                   |             |
        |                   |             +--> Field (Street)
        |                   |             |
        |                   |             +--> Field (Num)
        |                   |             | 
        |                   |             +--> Field (City)
        |                   |
        |                   +--> Horizontal Panel (Parents)
        |                        |
        |                        +--> Vertical Panel 
        |                             |   
        |                             +--> Horizontal Panel (line of controls)
        |                                  |
        |                                  +--> Field (Mom)
        |                                  |
        |                                  +--> Field (Dad)
        +--> Horizonal Panel (Sports) 
             |
             +--> Vertical Panel
                  |
                  +--> Horizontal Panel (line of controls)
                  |    |
                  |    +--> Field (First Sport)
                  |     
                  +--> Horizontal Panel (line of controls)

                       |                        


                       +--> Field (Second Sport)



Note that every group of fields (marked in OpenXava between brackets [..]) is formed by Horizontal Panel + Vertical panel 

Note that each line of controls is formed by a Horizontal Panel 

So the algorithm should identify the elements:

  • group of controls (between brackets [])
  • lines of controls (identified by comma and semicolons (,;)
  • controls 

2. Implementing Horizontal and Vertical Panels for containers and lines of controls in Vaadin

The simple Vaadin Div component and the CSS flex and @media  elements can perform the magic.

The @media is used for determining the form the components are arranged depending on the size of the screen (so we can predict if the user is managing a big screen, tablet or phone)

The flex element is used to wrap controls in a line (line of controls), so we do not need to worry about the length of the controls when they are contained in a line.

Here is  CSS code

/* For using with OX components.*/ 

/*----------------------------------------------------------*/
/* VERTICAL PANEL */
/*----------------------------------------------------------*/ 

/* For vetical layout */
 .flex-column {
    display: flex;
    flex-direction: column;
    flex: 1;
 }


/*----------------------------------------------------------*/
/* HORIZONTAL PANEL: BIG SCREENS */
/*----------------------------------------------------------*/ 
    /* For horizontal layout (line of controls) */
 .flex-row {
    display: flex;
    flex-direction: row;
    flex-wrap: wrap;
    width: 100%;
 }
 
 
 
 /*When sharing a horizontal with a number of group of controls*/
 .share-with-1 {
  width: 100%;
 }
 .share-with-2 {
  width: 50%;
 }
 .share-with-3 {
  width: 33%;
 }
 .share-with-4 {
  width: 25%;
 }
 .share-with-5 {
  width: 20%;
 }
 .share-with-6 {
  width: 16%;
 }
 .share-with-7 {
  width: 14%;
 }
 .share-with-8 {
  width: 12%;
 }
 .share-with-9 {
  width: 11%;
 }
 .share-with-10 {
  width: 10%;
 }
 
 
/*----------------------------------------------------------*/
/* HORIZONTAL PANEL: MEDIUM SCREENS */
/*----------------------------------------------------------*/ 
 @media all and (max-width: 1000px) {
    .flex-row  {
       /* When on medium sized screens, we center it by evenly distributing empty space around items */
       justify-content: space-around;
    }
    .share-with-1 {
       width: 100%;
    }
    .share-with-2 , .share-with-3 , .share-with-4 , .share-with-5 ,
    .share-with-6 , .share-with-7 , .share-with-8 , .share-with-8 ,
    .share-with-10 {
       width: 50%;
    }
 }

/*----------------------------------------------------------*/
/* HORIZONTAL PANEL: SMALL SCREENS */
/*----------------------------------------------------------*/ 
 @media all and (max-width: 600px) {
    .flex-row  {
     /* On small screens, we are no longer using row direction but column */
     flex-direction: column;
    }
   .share-with-1 , .share-with-2 , .share-with-3 , .share-with-4 ,
  .share-with-5 , .share-with-6 , .share-with-7 , .share-with-8 ,
  .share-with-9 , .share-with-10 {
   width: 100%;
  }
 }
 
 

The vertical panel properties are not affected by the screen size.

. However, horizontal panels must adapt to the width of the screen. (class flex-column)

For groups of controls in one line, in big displays, it is accepted up to 10 columns, in medium ones, 2 columns are accepted and in small devices only one column (class share-with-number_of_groups)

The lines of controls are managed with the flex component (class flex-row).  The behavior (number of columns) can vary depending on both the width of the controls (wrapping) and the width of the screen.



jueves, 14 de noviembre de 2019

27. Vaadin 14. Problem with styles. (3) TextArea

0. Introduction


This post should be used combined with the last two posts.

1. TextArea Styling

This object HAS NO REFERENCE TO the textboxes !!!

1.0 Assign the Vaaadin Theme (For instance Lumo)

1.1 Create a file that contains general values of styles assigned to variables for instance "shared-styles.css" in the "frontend/styles" folder of your project with this info. Note that this file was created in the previous post and no additional information has been added.


 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
html {
  /* Example global custom CSS property definition */
  
  /* 1. FORM FIELDS */
    /* 1.1 enabled */
    --ximo-field-color:                     black;
    --ximo-field-background-color:          white;
    --ximo-field-font-weight:               bold;
    --ximo-field-opacity:                   1.0;
  
    --ximo-field-border-radius:             10px;
    --ximo-field-border-width:              1px 2px 2px 1px;
    --ximo-field-border-style:              solid;
    --ximo-field-border-color:              salmon;
    --ximo-field-margin-right:              15px;
  
    /* 1.2 disabled */
    --ximo-field-disabled-color:            gray;
    --ximo-field-disabled-background-color: white;
    --ximo-field-disabled-font-weight:      bold;
    --ximo-field-disabled-opacity:          0.8;
  
    --ximo-field-disabled-border-radius:    10px;
    --ximo-field-disabled-border-width:     1px 2px 2px 1px;
    --ximo-field-disabled-border-style:     solid;
    --ximo-field-disabled-border-color:     thistle;
    --ximo-field-disabled-margin-right:     15px;
 
 
 /* 2. COMBOBOX */
    /* 1.1 App Selector*/
    --ximo-combo-color:                     maroon;;
    --ximo-combo-font-weight:               bold;
    --ximo-combo-background-image:          linear-gradient(to bottom right, lightpink, white);
    --ximo-combo-border-radius:             10px;
 
    --ximo-combo-border:                    2px;
    --ximo-combo-border-bottom-style:       solid;
    --ximo-combo-border-bottom-width:       medium;
    --ximo-combo-border-bottom-color:       saddlebrown;
}

1.2 The file  "my-textfield-styles.css" in the "frontend/styles" folder is not needed for TextAreas, although it is needed for TextBoxes and ComboBoxes

1.3 Create a file called for instance "current-textarea-styles.css" in the "frontend/styles" folder of your project with this info. These are the styles definitively assigned to TextAreas. Take care!


 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
/* General */
[part="input-field"] {
  
    color:                  var(--ximo-field-color);
    font-weight:            var(--ximo-field-font-weight);
    background-color:       var(--ximo-field-background-color);
    border-radius:          var(--ximo-field-border-radius);
    border-width:           var(--ximo-field-border-width);
    border-style:           var(--ximo-field-border-style);
    border-color:           var(--ximo-field-border-color);
    margin-right:           var(--ximo-field-margin-right);
    
    opacity:                var(--ximo-field-opacity);
    max-width:              35ch;
    min-width:              15ch;
    
    
    --lumo-disabled-text-color: var(--ximo-field-disabled-color);
  
 }
 
/* disabled */ 
:host([disabled]) [part="input-field"] { 
    border-color:      var(--ximo-field-disabled-border-color);
} 

/* For the label part of a text area */
[part="label"] {
    --lumo-disabled-text-color: var(--ximo-field-disabled-color);
} 

Take into account the different part of a TextArea ("input-field" and "label")

1.4 The class that holds the form should have a reference to all the "css" files, using @CssImport


 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
@PageTitle("MainView")
@Route("mainview")
//... other stuff ....

//General Vaadin theme
@Theme(value = Lumo.class)  //(1)

//@ see https://vaadin.com/forum/thread/17197360/17863614 from Niels Nachname
@CssImport(value="styles/my-textfield-styles.css", themeFor="vaadin-text-field") // (2) Select only Text fields
@CssImport("./styles/shared-styles.css")              // (3) General variable setting 
@CssImport("./styles/current-textfields-styles.css")  // (4) Applied style to TextFields using previous variables


@CssImport(value="styles/my-comboboxstyles.css" , themeFor="vaadin-combo-box") //(2A) Select only for Combos
@CssImport("./styles/current-combobox-styles.css")  // (4B) Applied style to TextFields using previous variables

@CssImport(value="styles/current-textareastyles.css" , themeFor="vaadin-text-area") //(2B) Select only for TextAreas


public class MainView extends VerticalLayout implements RouterLayout {

 private TextField myTF=new TextField();
 
 private ComboBox myCmb01=new ComboBox<>();
 private ComboBox myCmb02=new ComboBox<>();
 private ComboBox myCmb03=new ComboBox<>();

 private TextArea myTA=new TextArea();
        
 public MainView() { 
  myTF.setClassName("my-textfield"); //Important
  
  //myCmb01.setClassName("my-textfield"); --> No set classname for  MyCmb01 as gets general CSS of [part="text-field"]
  myCmb02.setClassName("my-combobox-app"); // See current-combobox-styles.css
  myCmb03.setClassName("my-combobox-opt"); // See current-combobox-styles.css

  // No need to set Class for the textArea
   
 }
 //...other stuff