Merge pull request #16134 from marcushellberg/master
Updates for vaadin intro article
This commit is contained in:
commit
b5bfa4697d
|
@ -0,0 +1 @@
|
|||
frontend/generated
|
|
@ -0,0 +1,23 @@
|
|||
<!DOCTYPE html>
|
||||
<!--
|
||||
This file is auto-generated by Vaadin.
|
||||
-->
|
||||
|
||||
<html>
|
||||
<head>
|
||||
<meta charset="UTF-8" />
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1" />
|
||||
<style>
|
||||
body, #outlet {
|
||||
height: 100vh;
|
||||
width: 100%;
|
||||
margin: 0;
|
||||
}
|
||||
</style>
|
||||
<!-- index.ts is included here automatically (either by the dev server or during the build) -->
|
||||
</head>
|
||||
<body>
|
||||
<!-- This outlet div is where the views are rendered -->
|
||||
<div id="outlet"></div>
|
||||
</body>
|
||||
</html>
|
180
vaadin/pom.xml
180
vaadin/pom.xml
|
@ -1,13 +1,12 @@
|
|||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<project xmlns="http://maven.apache.org/POM/4.0.0"
|
||||
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
||||
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
|
||||
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
||||
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
|
||||
<modelVersion>4.0.0</modelVersion>
|
||||
<groupId>org.test</groupId>
|
||||
<artifactId>vaadin</artifactId>
|
||||
<version>1.0-SNAPSHOT</version>
|
||||
<name>vaadin</name>
|
||||
<packaging>war</packaging>
|
||||
|
||||
<parent>
|
||||
<groupId>com.baeldung</groupId>
|
||||
|
@ -16,6 +15,11 @@
|
|||
<relativePath>../parent-boot-3</relativePath>
|
||||
</parent>
|
||||
|
||||
<properties>
|
||||
<java.version>17</java.version>
|
||||
<vaadin.version>24.3.3</vaadin.version>
|
||||
</properties>
|
||||
|
||||
<dependencyManagement>
|
||||
<dependencies>
|
||||
<dependency>
|
||||
|
@ -30,39 +34,24 @@
|
|||
|
||||
<dependencies>
|
||||
<dependency>
|
||||
<groupId>javax.servlet</groupId>
|
||||
<artifactId>javax.servlet-api</artifactId>
|
||||
<version>4.0.1</version>
|
||||
<scope>provided</scope>
|
||||
<groupId>com.vaadin</groupId>
|
||||
<artifactId>vaadin-core</artifactId>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>com.vaadin</groupId>
|
||||
<artifactId>vaadin-server</artifactId>
|
||||
<version>${vaadin-server.version}</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>com.vaadin</groupId>
|
||||
<artifactId>vaadin-push</artifactId>
|
||||
<version>${vaadin-push.version}</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>com.vaadin</groupId>
|
||||
<artifactId>vaadin-client-compiled</artifactId>
|
||||
<version>${vaadin-client-compiled.version}</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>com.vaadin</groupId>
|
||||
<artifactId>vaadin-themes</artifactId>
|
||||
<version>${vaadin-themes.version}</version>
|
||||
<artifactId>vaadin-spring-boot-starter</artifactId>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.springframework.boot</groupId>
|
||||
<artifactId>spring-boot-starter-data-jpa</artifactId>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>com.vaadin</groupId>
|
||||
<artifactId>vaadin-spring-boot-starter</artifactId>
|
||||
<version>${vaadin-spring-boot-starter.version}</version>
|
||||
<groupId>org.springframework.boot</groupId>
|
||||
<artifactId>spring-boot-starter-validation</artifactId>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>io.projectreactor</groupId>
|
||||
<artifactId>reactor-core</artifactId>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>com.h2database</groupId>
|
||||
|
@ -77,47 +66,17 @@
|
|||
|
||||
<build>
|
||||
<plugins>
|
||||
<plugin>
|
||||
<groupId>org.apache.maven.plugins</groupId>
|
||||
<artifactId>maven-war-plugin</artifactId>
|
||||
<version>${maven-war-plugin.version}</version>
|
||||
<configuration>
|
||||
<failOnMissingWebXml>false</failOnMissingWebXml>
|
||||
<!-- Exclude an unnecessary file generated by the GWT compiler. -->
|
||||
<packagingExcludes>WEB-INF/classes/VAADIN/widgetsets/WEB-INF/**</packagingExcludes>
|
||||
</configuration>
|
||||
</plugin>
|
||||
<plugin>
|
||||
<groupId>com.vaadin</groupId>
|
||||
<artifactId>vaadin-maven-plugin</artifactId>
|
||||
<version>${vaadin.plugin.version}</version>
|
||||
</plugin>
|
||||
<plugin>
|
||||
<groupId>org.apache.maven.plugins</groupId>
|
||||
<artifactId>maven-clean-plugin</artifactId>
|
||||
<version>${maven-clean-plugin.version}</version>
|
||||
<!-- Clean up also any pre-compiled themes -->
|
||||
<configuration>
|
||||
<filesets>
|
||||
<fileset>
|
||||
<directory>src/main/webapp/VAADIN/themes</directory>
|
||||
<includes>
|
||||
<include>**/styles.css</include>
|
||||
<include>**/styles.scss.cache</include>
|
||||
</includes>
|
||||
</fileset>
|
||||
</filesets>
|
||||
</configuration>
|
||||
</plugin>
|
||||
<!-- The Jetty plugin allows us to easily test the development build by running jetty:run -->
|
||||
<!-- on the command line. -->
|
||||
<plugin>
|
||||
<groupId>org.eclipse.jetty</groupId>
|
||||
<artifactId>jetty-maven-plugin</artifactId>
|
||||
<version>${jetty.plugin.version}</version>
|
||||
<configuration>
|
||||
<scanIntervalSeconds>2</scanIntervalSeconds>
|
||||
</configuration>
|
||||
<version>${vaadin.version}</version>
|
||||
<executions>
|
||||
<execution>
|
||||
<goals>
|
||||
<goal>prepare-frontend</goal>
|
||||
</goals>
|
||||
</execution>
|
||||
</executions>
|
||||
</plugin>
|
||||
<plugin>
|
||||
<groupId>org.springframework.boot</groupId>
|
||||
|
@ -126,68 +85,41 @@
|
|||
</plugins>
|
||||
</build>
|
||||
|
||||
<repositories>
|
||||
<repository>
|
||||
<id>vaadin-addons</id>
|
||||
<url>https://maven.vaadin.com/vaadin-addons</url>
|
||||
</repository>
|
||||
</repositories>
|
||||
|
||||
<profiles>
|
||||
<profile>
|
||||
<!-- Vaadin pre-release repositories -->
|
||||
<id>vaadin-prerelease</id>
|
||||
<activation>
|
||||
<activeByDefault>false</activeByDefault>
|
||||
</activation>
|
||||
|
||||
<repositories>
|
||||
<repository>
|
||||
<id>vaadin-prereleases</id>
|
||||
<url>https://maven.vaadin.com/vaadin-prereleases</url>
|
||||
</repository>
|
||||
<repository>
|
||||
<id>vaadin-snapshots</id>
|
||||
<url>https://oss.sonatype.org/content/repositories/vaadin-snapshots/</url>
|
||||
<releases>
|
||||
<enabled>false</enabled>
|
||||
</releases>
|
||||
<snapshots>
|
||||
<enabled>true</enabled>
|
||||
</snapshots>
|
||||
</repository>
|
||||
</repositories>
|
||||
<pluginRepositories>
|
||||
<pluginRepository>
|
||||
<id>vaadin-prereleases</id>
|
||||
<url>https://maven.vaadin.com/vaadin-prereleases</url>
|
||||
</pluginRepository>
|
||||
<pluginRepository>
|
||||
<id>vaadin-snapshots</id>
|
||||
<url>https://oss.sonatype.org/content/repositories/vaadin-snapshots/</url>
|
||||
<releases>
|
||||
<enabled>false</enabled>
|
||||
</releases>
|
||||
<snapshots>
|
||||
<enabled>true</enabled>
|
||||
</snapshots>
|
||||
</pluginRepository>
|
||||
</pluginRepositories>
|
||||
<!-- Production mode is activated using -Pproduction -->
|
||||
<id>production</id>
|
||||
<dependencies>
|
||||
<!-- Exclude development dependencies from production -->
|
||||
<dependency>
|
||||
<groupId>com.vaadin</groupId>
|
||||
<artifactId>vaadin-core</artifactId>
|
||||
<exclusions>
|
||||
<exclusion>
|
||||
<groupId>com.vaadin</groupId>
|
||||
<artifactId>vaadin-dev</artifactId>
|
||||
</exclusion>
|
||||
</exclusions>
|
||||
</dependency>
|
||||
</dependencies>
|
||||
<build>
|
||||
<plugins>
|
||||
<plugin>
|
||||
<groupId>com.vaadin</groupId>
|
||||
<artifactId>vaadin-maven-plugin</artifactId>
|
||||
<version>${vaadin.version}</version>
|
||||
<executions>
|
||||
<execution>
|
||||
<goals>
|
||||
<goal>build-frontend</goal>
|
||||
</goals>
|
||||
<phase>compile</phase>
|
||||
</execution>
|
||||
</executions>
|
||||
</plugin>
|
||||
</plugins>
|
||||
</build>
|
||||
</profile>
|
||||
</profiles>
|
||||
|
||||
<properties>
|
||||
<vaadin.version>13.0.9</vaadin.version>
|
||||
<vaadin.plugin.version>13.0.9</vaadin.plugin.version>
|
||||
<vaadin-spring-boot-starter.version>13.0.9</vaadin-spring-boot-starter.version>
|
||||
<vaadin-server.version>8.8.5</vaadin-server.version>
|
||||
<vaadin-push.version>8.8.5</vaadin-push.version>
|
||||
<vaadin-client-compiled.version>8.8.5</vaadin-client-compiled.version>
|
||||
<vaadin-themes.version>8.8.5</vaadin-themes.version>
|
||||
<jetty.plugin.version>9.3.9.v20160517</jetty.plugin.version>
|
||||
<vaadin.widgetset.mode>local</vaadin.widgetset.mode>
|
||||
<vaadin.theme>mytheme</vaadin.theme>
|
||||
<maven-clean-plugin.version>3.0.0</maven-clean-plugin.version>
|
||||
</properties>
|
||||
|
||||
</project>
|
|
@ -1,15 +1,19 @@
|
|||
package com.baeldung;
|
||||
|
||||
import com.baeldung.data.Employee;
|
||||
import com.baeldung.data.EmployeeRepository;
|
||||
import com.vaadin.flow.component.page.AppShellConfigurator;
|
||||
import com.vaadin.flow.component.page.Push;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
import org.springframework.boot.CommandLineRunner;
|
||||
import org.springframework.boot.SpringApplication;
|
||||
import org.springframework.boot.autoconfigure.SpringBootApplication;
|
||||
import org.springframework.context.annotation.Bean;
|
||||
|
||||
@Push
|
||||
@SpringBootApplication
|
||||
public class Application {
|
||||
public class Application implements AppShellConfigurator {
|
||||
|
||||
private static final Logger log = LoggerFactory.getLogger(Application.class);
|
||||
|
||||
|
|
|
@ -1,90 +0,0 @@
|
|||
package com.baeldung;
|
||||
|
||||
import com.vaadin.flow.component.Key;
|
||||
import com.vaadin.flow.component.KeyNotifier;
|
||||
import com.vaadin.flow.component.button.Button;
|
||||
import com.vaadin.flow.component.icon.VaadinIcon;
|
||||
import com.vaadin.flow.component.orderedlayout.HorizontalLayout;
|
||||
import com.vaadin.flow.component.orderedlayout.VerticalLayout;
|
||||
import com.vaadin.flow.component.textfield.TextField;
|
||||
import com.vaadin.flow.data.binder.Binder;
|
||||
import com.vaadin.flow.spring.annotation.SpringComponent;
|
||||
import com.vaadin.flow.spring.annotation.UIScope;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
|
||||
@SpringComponent
|
||||
@UIScope
|
||||
public class EmployeeEditor extends VerticalLayout implements KeyNotifier {
|
||||
|
||||
private final EmployeeRepository repository;
|
||||
|
||||
private Employee employee;
|
||||
|
||||
TextField firstName = new TextField("First name");
|
||||
TextField lastName = new TextField("Last name");
|
||||
|
||||
Button save = new Button("Save", VaadinIcon.CHECK.create());
|
||||
Button cancel = new Button("Cancel");
|
||||
Button delete = new Button("Delete", VaadinIcon.TRASH.create());
|
||||
HorizontalLayout actions = new HorizontalLayout(save, cancel, delete);
|
||||
|
||||
Binder<Employee> binder = new Binder<>(Employee.class);
|
||||
private ChangeHandler changeHandler;
|
||||
|
||||
@Autowired
|
||||
public EmployeeEditor(EmployeeRepository repository) {
|
||||
this.repository = repository;
|
||||
|
||||
add(firstName, lastName, actions);
|
||||
|
||||
binder.bindInstanceFields(this);
|
||||
|
||||
setSpacing(true);
|
||||
|
||||
save.getElement().getThemeList().add("primary");
|
||||
delete.getElement().getThemeList().add("error");
|
||||
|
||||
addKeyPressListener(Key.ENTER, e -> save());
|
||||
|
||||
save.addClickListener(e -> save());
|
||||
delete.addClickListener(e -> delete());
|
||||
cancel.addClickListener(e -> editEmployee(employee));
|
||||
setVisible(false);
|
||||
}
|
||||
|
||||
void delete() {
|
||||
repository.delete(employee);
|
||||
changeHandler.onChange();
|
||||
}
|
||||
|
||||
void save() {
|
||||
repository.save(employee);
|
||||
changeHandler.onChange();
|
||||
}
|
||||
|
||||
public interface ChangeHandler {
|
||||
void onChange();
|
||||
}
|
||||
|
||||
public final void editEmployee(Employee c) {
|
||||
if (c == null) {
|
||||
setVisible(false);
|
||||
return;
|
||||
}
|
||||
final boolean persisted = c.getId() != null;
|
||||
if (persisted) {
|
||||
employee = repository.findById(c.getId()).get();
|
||||
} else {
|
||||
employee = c;
|
||||
}
|
||||
|
||||
cancel.setVisible(persisted);
|
||||
binder.setBean(employee);
|
||||
setVisible(true);
|
||||
firstName.focus();
|
||||
}
|
||||
|
||||
public void setChangeHandler(ChangeHandler h) {
|
||||
changeHandler = h;
|
||||
}
|
||||
}
|
|
@ -0,0 +1,25 @@
|
|||
package com.baeldung;
|
||||
|
||||
import com.baeldung.introduction.PushView;
|
||||
import com.baeldung.introduction.basics.VaadinFlowBasics;
|
||||
import com.baeldung.introduction.FormView;
|
||||
import com.baeldung.introduction.GridView;
|
||||
import com.baeldung.spring.EmployeesView;
|
||||
import com.vaadin.flow.component.html.H1;
|
||||
import com.vaadin.flow.component.orderedlayout.VerticalLayout;
|
||||
import com.vaadin.flow.router.Route;
|
||||
import com.vaadin.flow.router.RouterLink;
|
||||
|
||||
@Route("")
|
||||
public class IndexView extends VerticalLayout {
|
||||
|
||||
public IndexView() {
|
||||
add(new H1("Vaadin Flow examples"));
|
||||
|
||||
add(new RouterLink("Basics", VaadinFlowBasics.class));
|
||||
add(new RouterLink("Grid", GridView.class));
|
||||
add(new RouterLink("Form", FormView.class));
|
||||
add(new RouterLink("Push", PushView.class));
|
||||
add(new RouterLink("CRUD", EmployeesView.class));
|
||||
}
|
||||
}
|
|
@ -1,67 +0,0 @@
|
|||
package com.baeldung;
|
||||
|
||||
import org.springframework.util.StringUtils;
|
||||
|
||||
import com.vaadin.flow.component.button.Button;
|
||||
import com.vaadin.flow.component.grid.Grid;
|
||||
import com.vaadin.flow.component.icon.VaadinIcon;
|
||||
import com.vaadin.flow.component.orderedlayout.HorizontalLayout;
|
||||
import com.vaadin.flow.component.orderedlayout.VerticalLayout;
|
||||
import com.vaadin.flow.component.textfield.TextField;
|
||||
import com.vaadin.flow.data.value.ValueChangeMode;
|
||||
import com.vaadin.flow.router.Route;
|
||||
|
||||
@Route
|
||||
public class MainView extends VerticalLayout {
|
||||
|
||||
private final EmployeeRepository employeeRepository;
|
||||
|
||||
private final EmployeeEditor editor;
|
||||
|
||||
final Grid<Employee> grid;
|
||||
|
||||
final TextField filter;
|
||||
|
||||
private final Button addNewBtn;
|
||||
|
||||
public MainView(EmployeeRepository repo, EmployeeEditor editor) {
|
||||
this.employeeRepository = repo;
|
||||
this.editor = editor;
|
||||
this.grid = new Grid<>(Employee.class);
|
||||
this.filter = new TextField();
|
||||
this.addNewBtn = new Button("New employee", VaadinIcon.PLUS.create());
|
||||
|
||||
HorizontalLayout actions = new HorizontalLayout(filter, addNewBtn);
|
||||
add(actions, grid, editor);
|
||||
|
||||
grid.setHeight("200px");
|
||||
grid.setColumns("id", "firstName", "lastName");
|
||||
grid.getColumnByKey("id").setWidth("50px").setFlexGrow(0);
|
||||
|
||||
filter.setPlaceholder("Filter by last name");
|
||||
|
||||
filter.setValueChangeMode(ValueChangeMode.EAGER);
|
||||
filter.addValueChangeListener(e -> listEmployees(e.getValue()));
|
||||
|
||||
grid.asSingleSelect().addValueChangeListener(e -> {
|
||||
editor.editEmployee(e.getValue());
|
||||
});
|
||||
|
||||
addNewBtn.addClickListener(e -> editor.editEmployee(new Employee("", "")));
|
||||
|
||||
editor.setChangeHandler(() -> {
|
||||
editor.setVisible(false);
|
||||
listEmployees(filter.getValue());
|
||||
});
|
||||
|
||||
listEmployees(null);
|
||||
}
|
||||
|
||||
void listEmployees(String filterText) {
|
||||
if (StringUtils.isEmpty(filterText)) {
|
||||
grid.setItems(employeeRepository.findAll());
|
||||
} else {
|
||||
grid.setItems(employeeRepository.findByLastNameStartsWithIgnoreCase(filterText));
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,73 @@
|
|||
package com.baeldung.data;
|
||||
|
||||
import jakarta.persistence.Entity;
|
||||
import jakarta.persistence.GeneratedValue;
|
||||
import jakarta.persistence.Id;
|
||||
import jakarta.validation.constraints.Email;
|
||||
import jakarta.validation.constraints.NotBlank;
|
||||
import jakarta.validation.constraints.Pattern;
|
||||
|
||||
@Entity
|
||||
public class Contact {
|
||||
|
||||
@Id
|
||||
@GeneratedValue
|
||||
private Long id;
|
||||
@NotBlank
|
||||
private String name;
|
||||
@Email
|
||||
private String email;
|
||||
@Pattern(regexp = "\\d{3}-\\d{3}-\\d{4}")
|
||||
private String phone;
|
||||
|
||||
public Contact() {
|
||||
}
|
||||
|
||||
public Contact(String name, String email, String phone) {
|
||||
this.name = name;
|
||||
this.email = email;
|
||||
this.phone = phone;
|
||||
}
|
||||
|
||||
public Long getId() {
|
||||
return id;
|
||||
}
|
||||
|
||||
public void setId(Long id) {
|
||||
this.id = id;
|
||||
}
|
||||
|
||||
public String getName() {
|
||||
return name;
|
||||
}
|
||||
|
||||
public void setName(String name) {
|
||||
this.name = name;
|
||||
}
|
||||
|
||||
public String getEmail() {
|
||||
return email;
|
||||
}
|
||||
|
||||
public void setEmail(String email) {
|
||||
this.email = email;
|
||||
}
|
||||
|
||||
public String getPhone() {
|
||||
return phone;
|
||||
}
|
||||
|
||||
public void setPhone(String phone) {
|
||||
this.phone = phone;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return "Contact {" +
|
||||
"id=" + id +
|
||||
", name='" + name + "'" +
|
||||
", email='" + email + "'" +
|
||||
", phone='" + phone + "'" +
|
||||
" }";
|
||||
}
|
||||
}
|
|
@ -0,0 +1,6 @@
|
|||
package com.baeldung.data;
|
||||
|
||||
import org.springframework.data.jpa.repository.JpaRepository;
|
||||
|
||||
public interface ContactRepository extends JpaRepository<Contact, Long> {
|
||||
}
|
|
@ -0,0 +1,46 @@
|
|||
package com.baeldung.data;
|
||||
|
||||
import org.springframework.boot.CommandLineRunner;
|
||||
import org.springframework.stereotype.Component;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.Random;
|
||||
|
||||
@Component
|
||||
public class DataInitializer implements CommandLineRunner {
|
||||
|
||||
private final ContactRepository contactRepository;
|
||||
|
||||
public DataInitializer(ContactRepository contactRepository) {
|
||||
this.contactRepository = contactRepository;
|
||||
}
|
||||
|
||||
private final List<String> firstNames = List.of(
|
||||
"John", "Jane", "Emily", "Michael", "Sarah", "James", "Mary", "Robert",
|
||||
"Patricia", "William", "Linda", "David", "Barbara", "Richard", "Susan",
|
||||
"Joseph", "Jessica", "Thomas", "Karen", "Charles"
|
||||
);
|
||||
private final List<String> lastNames = List.of(
|
||||
"Doe", "Smith", "Johnson", "Brown", "Davis", "Miller", "Wilson", "Moore",
|
||||
"Taylor", "Anderson", "Thomas", "Jackson", "White", "Harris", "Martin",
|
||||
"Thompson", "Garcia", "Martinez", "Robinson", "Clark"
|
||||
);
|
||||
|
||||
@Override
|
||||
public void run(String... args) throws Exception {
|
||||
var contacts = new ArrayList<Contact>();
|
||||
Random random = new Random();
|
||||
|
||||
for (int i = 0; i < 100; i++) {
|
||||
String firstName = firstNames.get(random.nextInt(firstNames.size()));
|
||||
String lastName = lastNames.get(random.nextInt(lastNames.size()));
|
||||
String email = String.format("%s.%s@example.com", firstName.toLowerCase(), lastName.toLowerCase());
|
||||
String phone = String.format("555-%03d-%04d", random.nextInt(1000), random.nextInt(10000));
|
||||
|
||||
contacts.add(new Contact(firstName + " " + lastName, email, phone));
|
||||
}
|
||||
|
||||
contactRepository.saveAll(contacts);
|
||||
}
|
||||
}
|
|
@ -1,8 +1,10 @@
|
|||
package com.baeldung;
|
||||
package com.baeldung.data;
|
||||
|
||||
|
||||
import jakarta.persistence.Entity;
|
||||
import jakarta.persistence.GeneratedValue;
|
||||
import jakarta.persistence.Id;
|
||||
import jakarta.validation.constraints.Size;
|
||||
|
||||
@Entity
|
||||
public class Employee {
|
||||
|
@ -11,11 +13,13 @@ public class Employee {
|
|||
@GeneratedValue
|
||||
private Long id;
|
||||
|
||||
@Size(min = 2, message = "First name must have at least 2 characters")
|
||||
private String firstName;
|
||||
|
||||
@Size(min = 2, message = "Last name must have at least 2 characters")
|
||||
private String lastName;
|
||||
|
||||
protected Employee() {
|
||||
public Employee() {
|
||||
}
|
||||
|
||||
public Employee(String firstName, String lastName) {
|
||||
|
@ -27,6 +31,10 @@ public class Employee {
|
|||
return id;
|
||||
}
|
||||
|
||||
public void setId(Long id) {
|
||||
this.id = id;
|
||||
}
|
||||
|
||||
public String getFirstName() {
|
||||
return firstName;
|
||||
}
|
|
@ -1,4 +1,4 @@
|
|||
package com.baeldung;
|
||||
package com.baeldung.data;
|
||||
|
||||
import java.util.List;
|
||||
|
|
@ -1,20 +0,0 @@
|
|||
package com.baeldung.introduction;
|
||||
|
||||
public class BindData {
|
||||
|
||||
private String bindName;
|
||||
|
||||
public BindData(String bindName){
|
||||
this.bindName = bindName;
|
||||
}
|
||||
|
||||
public String getBindName() {
|
||||
return bindName;
|
||||
}
|
||||
|
||||
public void setBindName(String bindName) {
|
||||
this.bindName = bindName;
|
||||
}
|
||||
|
||||
|
||||
}
|
|
@ -0,0 +1,88 @@
|
|||
package com.baeldung.introduction;
|
||||
|
||||
import com.baeldung.data.Contact;
|
||||
import com.vaadin.flow.component.button.Button;
|
||||
import com.vaadin.flow.component.html.H2;
|
||||
import com.vaadin.flow.component.notification.Notification;
|
||||
import com.vaadin.flow.component.orderedlayout.HorizontalLayout;
|
||||
import com.vaadin.flow.component.orderedlayout.VerticalLayout;
|
||||
import com.vaadin.flow.component.textfield.TextField;
|
||||
import com.vaadin.flow.data.binder.BeanValidationBinder;
|
||||
import com.vaadin.flow.data.binder.Binder;
|
||||
import com.vaadin.flow.router.Route;
|
||||
|
||||
@Route("form")
|
||||
public class FormView extends HorizontalLayout {
|
||||
|
||||
public FormView() {
|
||||
addBeanValidationExample();
|
||||
addCustomValidationExample();
|
||||
}
|
||||
|
||||
private void addBeanValidationExample() {
|
||||
var nameField = new TextField("Name");
|
||||
var emailField = new TextField("Email");
|
||||
var phoneField = new TextField("Phone");
|
||||
var saveButton = new Button("Save");
|
||||
|
||||
var binder = new BeanValidationBinder<>(Contact.class);
|
||||
|
||||
binder.forField(nameField).bind(Contact::getName, Contact::setName);
|
||||
binder.forField(emailField).bind(Contact::getEmail, Contact::setEmail);
|
||||
binder.forField(phoneField).bind(Contact::getPhone, Contact::setPhone);
|
||||
|
||||
var contact = new Contact("John Doe", "john@doe.com", "123-456-7890");
|
||||
binder.setBean(contact);
|
||||
|
||||
saveButton.addClickListener(e -> {
|
||||
if (binder.validate().isOk()) {
|
||||
Notification.show("Saved " + contact);
|
||||
}
|
||||
});
|
||||
|
||||
add(new VerticalLayout(
|
||||
new H2("Bean Validation Example"),
|
||||
nameField,
|
||||
emailField,
|
||||
phoneField,
|
||||
saveButton
|
||||
));
|
||||
}
|
||||
|
||||
private void addCustomValidationExample() {
|
||||
|
||||
var nameField = new TextField("Name");
|
||||
var emailField = new TextField("Email");
|
||||
var phoneField = new TextField("Phone");
|
||||
var saveButton = new Button("Save");
|
||||
|
||||
var binder = new Binder<>(Contact.class);
|
||||
|
||||
binder.forField(nameField)
|
||||
.asRequired()
|
||||
.bind(Contact::getName, Contact::setName);
|
||||
binder.forField(emailField)
|
||||
.withValidator(email -> email.contains("@"), "Not a valid email address")
|
||||
.bind(Contact::getEmail, Contact::setEmail);
|
||||
binder.forField(phoneField)
|
||||
.withValidator(phone -> phone.matches("\\d{3}-\\d{3}-\\d{4}"), "Not a valid phone number")
|
||||
.bind(Contact::getPhone, Contact::setPhone);
|
||||
|
||||
var contact = new Contact("John Doe", "john@doe.com", "123-456-7890");
|
||||
binder.setBean(contact);
|
||||
|
||||
saveButton.addClickListener(e -> {
|
||||
if (binder.validate().isOk()) {
|
||||
Notification.show("Saved " + contact);
|
||||
}
|
||||
});
|
||||
|
||||
add(new VerticalLayout(
|
||||
new H2("Custom Validation Example"),
|
||||
nameField,
|
||||
emailField,
|
||||
phoneField,
|
||||
saveButton
|
||||
));
|
||||
}
|
||||
}
|
|
@ -0,0 +1,40 @@
|
|||
package com.baeldung.introduction;
|
||||
|
||||
import com.baeldung.data.Contact;
|
||||
import com.baeldung.data.ContactRepository;
|
||||
import com.vaadin.flow.component.grid.Grid;
|
||||
import com.vaadin.flow.component.html.H1;
|
||||
import com.vaadin.flow.component.orderedlayout.VerticalLayout;
|
||||
import com.vaadin.flow.router.Route;
|
||||
import com.vaadin.flow.spring.data.VaadinSpringDataHelpers;
|
||||
|
||||
@Route("grid")
|
||||
public class GridView extends VerticalLayout {
|
||||
|
||||
public GridView(ContactRepository contactRepository) {
|
||||
|
||||
add(new H1("Using data grids"));
|
||||
|
||||
// Define a grid for a Contact entity
|
||||
var grid = new Grid<Contact>();
|
||||
grid.addColumn(Contact::getName).setHeader("Name");
|
||||
grid.addColumn(Contact::getEmail).setHeader("Email");
|
||||
grid.addColumn(Contact::getPhone).setHeader("Phone");
|
||||
|
||||
// There are two ways to populate the grid with data:
|
||||
|
||||
// 1) In-memory with a list of items
|
||||
var contacts = contactRepository.findAll();
|
||||
grid.setItems(contacts);
|
||||
|
||||
// 2) with a callback to lazily load items from a data source.
|
||||
grid.setItems(query -> {
|
||||
// Turn the page, offset, filter, sort and other info in query into a Spring Data PageRequest
|
||||
var pageRequest = VaadinSpringDataHelpers.toSpringPageRequest(query);
|
||||
return contactRepository.findAll(pageRequest).stream();
|
||||
});
|
||||
|
||||
add(grid);
|
||||
|
||||
}
|
||||
}
|
|
@ -0,0 +1,32 @@
|
|||
package com.baeldung.introduction;
|
||||
|
||||
import com.vaadin.flow.component.html.Span;
|
||||
import com.vaadin.flow.component.orderedlayout.VerticalLayout;
|
||||
import com.vaadin.flow.router.Route;
|
||||
import reactor.core.publisher.Flux;
|
||||
|
||||
import java.time.Duration;
|
||||
import java.time.Instant;
|
||||
|
||||
// Ensure you have @Push annotation in your Application class
|
||||
@Route("push")
|
||||
public class PushView extends VerticalLayout {
|
||||
|
||||
public PushView() {
|
||||
var output = new Span();
|
||||
|
||||
// Publish server time once a second
|
||||
var serverTime = Flux.interval(Duration.ofSeconds(1))
|
||||
.map(o -> "Server time: " + Instant.now());
|
||||
|
||||
|
||||
serverTime.subscribe(time ->
|
||||
// ui.access is required to update the UI from a background thread
|
||||
getUI().ifPresent(ui ->
|
||||
ui.access(() -> output.setText(time))
|
||||
)
|
||||
);
|
||||
|
||||
add(output);
|
||||
}
|
||||
}
|
|
@ -1,45 +0,0 @@
|
|||
package com.baeldung.introduction;
|
||||
|
||||
public class Row {
|
||||
|
||||
private String column1;
|
||||
|
||||
private String column2;
|
||||
|
||||
private String column3;
|
||||
|
||||
public Row() {
|
||||
|
||||
}
|
||||
|
||||
public Row(String column1, String column2, String column3) {
|
||||
super();
|
||||
this.column1 = column1;
|
||||
this.column2 = column2;
|
||||
this.column3 = column3;
|
||||
}
|
||||
|
||||
public String getColumn1() {
|
||||
return column1;
|
||||
}
|
||||
|
||||
public void setColumn1(String column1) {
|
||||
this.column1 = column1;
|
||||
}
|
||||
|
||||
public String getColumn2() {
|
||||
return column2;
|
||||
}
|
||||
|
||||
public void setColumn2(String column2) {
|
||||
this.column2 = column2;
|
||||
}
|
||||
|
||||
public String getColumn3() {
|
||||
return column3;
|
||||
}
|
||||
|
||||
public void setColumn3(String column3) {
|
||||
this.column3 = column3;
|
||||
}
|
||||
}
|
|
@ -1,281 +0,0 @@
|
|||
package com.baeldung.introduction;
|
||||
|
||||
import java.time.Instant;
|
||||
import java.time.LocalDate;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.concurrent.Executors;
|
||||
import java.util.concurrent.ScheduledExecutorService;
|
||||
import java.util.concurrent.TimeUnit;
|
||||
|
||||
import com.vaadin.annotations.Push;
|
||||
import com.vaadin.annotations.Theme;
|
||||
import com.vaadin.annotations.VaadinServletConfiguration;
|
||||
import com.vaadin.data.Binder;
|
||||
import com.vaadin.data.validator.StringLengthValidator;
|
||||
import com.vaadin.icons.VaadinIcons;
|
||||
import com.vaadin.server.ExternalResource;
|
||||
import com.vaadin.server.VaadinRequest;
|
||||
import com.vaadin.server.VaadinServlet;
|
||||
import com.vaadin.ui.Button;
|
||||
import com.vaadin.ui.CheckBox;
|
||||
import com.vaadin.ui.ComboBox;
|
||||
import com.vaadin.ui.DateField;
|
||||
import com.vaadin.ui.FormLayout;
|
||||
import com.vaadin.ui.Grid;
|
||||
import com.vaadin.ui.GridLayout;
|
||||
import com.vaadin.ui.HorizontalLayout;
|
||||
import com.vaadin.ui.InlineDateField;
|
||||
import com.vaadin.ui.Label;
|
||||
import com.vaadin.ui.Link;
|
||||
import com.vaadin.ui.ListSelect;
|
||||
import com.vaadin.ui.NativeButton;
|
||||
import com.vaadin.ui.NativeSelect;
|
||||
import com.vaadin.ui.Panel;
|
||||
import com.vaadin.ui.PasswordField;
|
||||
import com.vaadin.ui.RichTextArea;
|
||||
import com.vaadin.ui.TextArea;
|
||||
import com.vaadin.ui.TextField;
|
||||
import com.vaadin.ui.TwinColSelect;
|
||||
import com.vaadin.ui.UI;
|
||||
import com.vaadin.ui.VerticalLayout;
|
||||
import jakarta.servlet.annotation.WebServlet;
|
||||
|
||||
@SuppressWarnings("serial")
|
||||
@Push
|
||||
@Theme("mytheme")
|
||||
public class VaadinUI extends UI {
|
||||
|
||||
private Label currentTime;
|
||||
|
||||
@SuppressWarnings({ "rawtypes", "unchecked" })
|
||||
@Override
|
||||
protected void init(VaadinRequest vaadinRequest) {
|
||||
final VerticalLayout verticalLayout = new VerticalLayout();
|
||||
verticalLayout.setSpacing(true);
|
||||
verticalLayout.setMargin(true);
|
||||
final GridLayout gridLayout = new GridLayout(3, 2);
|
||||
gridLayout.setSpacing(true);
|
||||
gridLayout.setMargin(true);
|
||||
final HorizontalLayout horizontalLayout = new HorizontalLayout();
|
||||
horizontalLayout.setSpacing(true);
|
||||
horizontalLayout.setMargin(true);
|
||||
final FormLayout formLayout = new FormLayout();
|
||||
formLayout.setSpacing(true);
|
||||
formLayout.setMargin(true);
|
||||
final GridLayout buttonLayout = new GridLayout(3, 5);
|
||||
buttonLayout.setMargin(true);
|
||||
buttonLayout.setSpacing(true);
|
||||
|
||||
final Label label = new Label();
|
||||
label.setId("Label");
|
||||
label.setValue("Label Value");
|
||||
label.setCaption("Label");
|
||||
gridLayout.addComponent(label);
|
||||
|
||||
final Link link = new Link("Baeldung", new ExternalResource("http://www.baeldung.com/"));
|
||||
link.setId("Link");
|
||||
link.setTargetName("_blank");
|
||||
gridLayout.addComponent(link);
|
||||
|
||||
final TextField textField = new TextField();
|
||||
textField.setId("TextField");
|
||||
textField.setCaption("TextField:");
|
||||
textField.setValue("TextField Value");
|
||||
textField.setIcon(VaadinIcons.USER);
|
||||
gridLayout.addComponent(textField);
|
||||
|
||||
final TextArea textArea = new TextArea();
|
||||
textArea.setCaption("TextArea");
|
||||
textArea.setId("TextArea");
|
||||
textArea.setValue("TextArea Value");
|
||||
gridLayout.addComponent(textArea);
|
||||
|
||||
final DateField dateField = new DateField("DateField", LocalDate.ofEpochDay(0));
|
||||
dateField.setId("DateField");
|
||||
gridLayout.addComponent(dateField);
|
||||
|
||||
final PasswordField passwordField = new PasswordField();
|
||||
passwordField.setId("PasswordField");
|
||||
passwordField.setCaption("PasswordField:");
|
||||
passwordField.setValue("password");
|
||||
gridLayout.addComponent(passwordField);
|
||||
|
||||
final RichTextArea richTextArea = new RichTextArea();
|
||||
richTextArea.setCaption("Rich Text Area");
|
||||
richTextArea.setValue("<h1>RichTextArea</h1>");
|
||||
richTextArea.setSizeFull();
|
||||
|
||||
Panel richTextPanel = new Panel();
|
||||
richTextPanel.setContent(richTextArea);
|
||||
|
||||
final InlineDateField inlineDateField = new InlineDateField();
|
||||
inlineDateField.setValue(LocalDate.ofEpochDay(0));
|
||||
inlineDateField.setCaption("Inline Date Field");
|
||||
horizontalLayout.addComponent(inlineDateField);
|
||||
|
||||
Button normalButton = new Button("Normal Button");
|
||||
normalButton.setId("NormalButton");
|
||||
normalButton.addClickListener(e -> {
|
||||
label.setValue("CLICK");
|
||||
});
|
||||
buttonLayout.addComponent(normalButton);
|
||||
|
||||
Button tinyButton = new Button("Tiny Button");
|
||||
tinyButton.addStyleName("tiny");
|
||||
buttonLayout.addComponent(tinyButton);
|
||||
|
||||
Button smallButton = new Button("Small Button");
|
||||
smallButton.addStyleName("small");
|
||||
buttonLayout.addComponent(smallButton);
|
||||
|
||||
Button largeButton = new Button("Large Button");
|
||||
largeButton.addStyleName("large");
|
||||
buttonLayout.addComponent(largeButton);
|
||||
|
||||
Button hugeButton = new Button("Huge Button");
|
||||
hugeButton.addStyleName("huge");
|
||||
buttonLayout.addComponent(hugeButton);
|
||||
|
||||
Button disabledButton = new Button("Disabled Button");
|
||||
disabledButton.setDescription("This button cannot be clicked");
|
||||
disabledButton.setEnabled(false);
|
||||
buttonLayout.addComponent(disabledButton);
|
||||
|
||||
Button dangerButton = new Button("Danger Button");
|
||||
dangerButton.addStyleName("danger");
|
||||
buttonLayout.addComponent(dangerButton);
|
||||
|
||||
Button friendlyButton = new Button("Friendly Button");
|
||||
friendlyButton.addStyleName("friendly");
|
||||
buttonLayout.addComponent(friendlyButton);
|
||||
|
||||
Button primaryButton = new Button("Primary Button");
|
||||
primaryButton.addStyleName("primary");
|
||||
buttonLayout.addComponent(primaryButton);
|
||||
|
||||
NativeButton nativeButton = new NativeButton("Native Button");
|
||||
buttonLayout.addComponent(nativeButton);
|
||||
|
||||
Button iconButton = new Button("Icon Button");
|
||||
iconButton.setIcon(VaadinIcons.ALIGN_LEFT);
|
||||
buttonLayout.addComponent(iconButton);
|
||||
|
||||
Button borderlessButton = new Button("BorderLess Button");
|
||||
borderlessButton.addStyleName("borderless");
|
||||
buttonLayout.addComponent(borderlessButton);
|
||||
|
||||
Button linkButton = new Button("Link Button");
|
||||
linkButton.addStyleName("link");
|
||||
buttonLayout.addComponent(linkButton);
|
||||
|
||||
Button quietButton = new Button("Quiet Button");
|
||||
quietButton.addStyleName("quiet");
|
||||
buttonLayout.addComponent(quietButton);
|
||||
|
||||
horizontalLayout.addComponent(buttonLayout);
|
||||
|
||||
final CheckBox checkbox = new CheckBox("CheckBox");
|
||||
checkbox.setValue(true);
|
||||
checkbox.addValueChangeListener(e -> checkbox.setValue(!checkbox.getValue()));
|
||||
formLayout.addComponent(checkbox);
|
||||
|
||||
List<String> numbers = new ArrayList<String>();
|
||||
numbers.add("One");
|
||||
numbers.add("Ten");
|
||||
numbers.add("Eleven");
|
||||
ComboBox comboBox = new ComboBox("ComboBox");
|
||||
comboBox.setItems(numbers);
|
||||
formLayout.addComponent(comboBox);
|
||||
|
||||
ListSelect listSelect = new ListSelect("ListSelect");
|
||||
listSelect.setItems(numbers);
|
||||
listSelect.setRows(2);
|
||||
formLayout.addComponent(listSelect);
|
||||
|
||||
NativeSelect nativeSelect = new NativeSelect("NativeSelect");
|
||||
nativeSelect.setItems(numbers);
|
||||
formLayout.addComponent(nativeSelect);
|
||||
|
||||
TwinColSelect twinColSelect = new TwinColSelect("TwinColSelect");
|
||||
twinColSelect.setItems(numbers);
|
||||
|
||||
Grid<Row> grid = new Grid(Row.class);
|
||||
grid.setColumns("column1", "column2", "column3");
|
||||
Row row1 = new Row("Item1", "Item2", "Item3");
|
||||
Row row2 = new Row("Item4", "Item5", "Item6");
|
||||
List<Row> rows = new ArrayList();
|
||||
rows.add(row1);
|
||||
rows.add(row2);
|
||||
grid.setItems(rows);
|
||||
|
||||
Panel panel = new Panel("Panel");
|
||||
panel.setContent(grid);
|
||||
panel.setSizeUndefined();
|
||||
|
||||
Panel serverPushPanel = new Panel("Server Push");
|
||||
FormLayout timeLayout = new FormLayout();
|
||||
timeLayout.setSpacing(true);
|
||||
timeLayout.setMargin(true);
|
||||
currentTime = new Label("No TIME...");
|
||||
timeLayout.addComponent(currentTime);
|
||||
serverPushPanel.setContent(timeLayout);
|
||||
serverPushPanel.setSizeUndefined();
|
||||
ScheduledExecutorService scheduleExecutor = Executors.newScheduledThreadPool(1);
|
||||
Runnable task = () -> {
|
||||
currentTime.setValue("Current Time : " + Instant.now());
|
||||
};
|
||||
scheduleExecutor.scheduleWithFixedDelay(task, 0, 1, TimeUnit.SECONDS);
|
||||
|
||||
FormLayout dataBindingLayout = new FormLayout();
|
||||
dataBindingLayout.setSpacing(true);
|
||||
dataBindingLayout.setMargin(true);
|
||||
|
||||
Binder<BindData> binder = new Binder<>();
|
||||
BindData bindData = new BindData("BindData");
|
||||
binder.readBean(bindData);
|
||||
TextField bindedTextField = new TextField();
|
||||
bindedTextField.setWidth("250px");
|
||||
binder.forField(bindedTextField).bind(BindData::getBindName, BindData::setBindName);
|
||||
dataBindingLayout.addComponent(bindedTextField);
|
||||
|
||||
FormLayout validatorLayout = new FormLayout();
|
||||
validatorLayout.setSpacing(true);
|
||||
validatorLayout.setMargin(true);
|
||||
|
||||
HorizontalLayout textValidatorLayout = new HorizontalLayout();
|
||||
textValidatorLayout.setSpacing(true);
|
||||
textValidatorLayout.setMargin(true);
|
||||
|
||||
|
||||
BindData stringValidatorBindData = new BindData("");
|
||||
TextField stringValidator = new TextField();
|
||||
Binder<BindData> stringValidatorBinder = new Binder<>();
|
||||
stringValidatorBinder.setBean(stringValidatorBindData);
|
||||
stringValidatorBinder.forField(stringValidator)
|
||||
.withValidator(new StringLengthValidator("String must have 2-5 characters lenght", 2, 5))
|
||||
.bind(BindData::getBindName, BindData::setBindName);
|
||||
|
||||
textValidatorLayout.addComponent(stringValidator);
|
||||
Button buttonStringValidator = new Button("Validate String");
|
||||
buttonStringValidator.addClickListener(e -> stringValidatorBinder.validate());
|
||||
textValidatorLayout.addComponent(buttonStringValidator);
|
||||
|
||||
validatorLayout.addComponent(textValidatorLayout);
|
||||
verticalLayout.addComponent(gridLayout);
|
||||
verticalLayout.addComponent(richTextPanel);
|
||||
verticalLayout.addComponent(horizontalLayout);
|
||||
verticalLayout.addComponent(formLayout);
|
||||
verticalLayout.addComponent(twinColSelect);
|
||||
verticalLayout.addComponent(panel);
|
||||
verticalLayout.addComponent(serverPushPanel);
|
||||
verticalLayout.addComponent(dataBindingLayout);
|
||||
verticalLayout.addComponent(validatorLayout);
|
||||
setContent(verticalLayout);
|
||||
}
|
||||
|
||||
@WebServlet(urlPatterns = "/VAADIN/*", name = "MyUIServlet", asyncSupported = true)
|
||||
@VaadinServletConfiguration(ui = VaadinUI.class, productionMode = false)
|
||||
public static class MyUIServlet extends VaadinServlet {
|
||||
}
|
||||
}
|
|
@ -0,0 +1,45 @@
|
|||
package com.baeldung.introduction.basics;
|
||||
|
||||
import com.baeldung.data.Contact;
|
||||
import com.vaadin.flow.component.button.Button;
|
||||
import com.vaadin.flow.component.grid.Grid;
|
||||
import com.vaadin.flow.component.orderedlayout.HorizontalLayout;
|
||||
import com.vaadin.flow.component.orderedlayout.VerticalLayout;
|
||||
import com.vaadin.flow.component.splitlayout.SplitLayout;
|
||||
import com.vaadin.flow.component.textfield.TextField;
|
||||
import com.vaadin.flow.router.Route;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
@Route("example-layout")
|
||||
public class ExampleLayout extends SplitLayout {
|
||||
|
||||
public ExampleLayout() {
|
||||
var grid = new Grid<>(Contact.class);
|
||||
grid.setColumns("name", "email", "phone");
|
||||
grid.setItems(List.of(
|
||||
new Contact("John Doe", "john@doe.com", "123 456 789"),
|
||||
new Contact("Jane Doe", "jane@doe.com", "987 654 321")
|
||||
));
|
||||
|
||||
var form = new VerticalLayout();
|
||||
|
||||
var nameField = new TextField("Name");
|
||||
var emailField = new TextField("Email");
|
||||
var phoneField = new TextField("Phone");
|
||||
var saveButton = new Button("Save");
|
||||
var cancelButton = new Button("Cancel");
|
||||
|
||||
form.add(
|
||||
nameField,
|
||||
emailField,
|
||||
phoneField,
|
||||
new HorizontalLayout(saveButton, cancelButton)
|
||||
);
|
||||
|
||||
setSizeFull();
|
||||
setSplitterPosition(70);
|
||||
addToPrimary(grid);
|
||||
addToSecondary(form);
|
||||
}
|
||||
}
|
|
@ -0,0 +1,13 @@
|
|||
package com.baeldung.introduction.basics;
|
||||
|
||||
import com.vaadin.flow.component.html.H1;
|
||||
import com.vaadin.flow.component.orderedlayout.VerticalLayout;
|
||||
import com.vaadin.flow.router.Route;
|
||||
|
||||
@Route("hello-world")
|
||||
public class HelloWorldView extends VerticalLayout {
|
||||
|
||||
public HelloWorldView() {
|
||||
add(new H1("Hello, World!"));
|
||||
}
|
||||
}
|
|
@ -0,0 +1,63 @@
|
|||
package com.baeldung.introduction.basics;
|
||||
|
||||
import com.vaadin.flow.component.button.Button;
|
||||
import com.vaadin.flow.component.checkbox.Checkbox;
|
||||
import com.vaadin.flow.component.html.H1;
|
||||
import com.vaadin.flow.component.notification.Notification;
|
||||
import com.vaadin.flow.component.orderedlayout.HorizontalLayout;
|
||||
import com.vaadin.flow.component.orderedlayout.VerticalLayout;
|
||||
import com.vaadin.flow.component.textfield.TextField;
|
||||
import com.vaadin.flow.router.Route;
|
||||
import com.vaadin.flow.router.RouterLink;
|
||||
|
||||
// The @Route annotation defines the URL path for the view
|
||||
// Any component, most commonly a layout, can be used as a view
|
||||
@Route("basics")
|
||||
public class VaadinFlowBasics extends VerticalLayout {
|
||||
public VaadinFlowBasics() {
|
||||
|
||||
// Add components to the layout with the add method
|
||||
add(new H1("Vaadin Flow Basics"));
|
||||
|
||||
// Components are Java objects
|
||||
var textField = new TextField("Name");
|
||||
var button = new Button("Click me");
|
||||
|
||||
// Layouts define the structure of the UI
|
||||
var verticalLayout = new VerticalLayout(
|
||||
new Button("Top"),
|
||||
new Button("Middle"),
|
||||
new Button("Bottom")
|
||||
);
|
||||
add(verticalLayout);
|
||||
|
||||
var horizontalLayout = new HorizontalLayout(
|
||||
new Button("Left"),
|
||||
new Button("Center"),
|
||||
new Button("Right")
|
||||
);
|
||||
add(horizontalLayout);
|
||||
|
||||
// Layouts can be nested for more complex structures
|
||||
var nestedLayout = new VerticalLayout(
|
||||
new HorizontalLayout(new Button("Top Left"), new Button("Top Right")),
|
||||
new HorizontalLayout(new Button("Bottom Left"), new Button("Bottom Right"))
|
||||
);
|
||||
add(nestedLayout);
|
||||
|
||||
add(new RouterLink("Example layout", ExampleLayout.class));
|
||||
|
||||
// Use RouterLink to navigate to other views
|
||||
var link = new RouterLink("Hello world view", HelloWorldView.class);
|
||||
add(link);
|
||||
|
||||
// Use events to react to user input
|
||||
var nameField = new TextField("Your name");
|
||||
var helloButton = new Button("Say hello");
|
||||
helloButton.addClickListener(e -> {
|
||||
Notification.show("Hello, " + nameField.getValue());
|
||||
});
|
||||
add(nameField, helloButton);
|
||||
|
||||
}
|
||||
}
|
|
@ -0,0 +1,86 @@
|
|||
package com.baeldung.spring;
|
||||
|
||||
import com.baeldung.data.Employee;
|
||||
import com.vaadin.flow.component.Composite;
|
||||
import com.vaadin.flow.component.Key;
|
||||
import com.vaadin.flow.component.button.Button;
|
||||
import com.vaadin.flow.component.button.ButtonVariant;
|
||||
import com.vaadin.flow.component.icon.VaadinIcon;
|
||||
import com.vaadin.flow.component.orderedlayout.HorizontalLayout;
|
||||
import com.vaadin.flow.component.orderedlayout.VerticalLayout;
|
||||
import com.vaadin.flow.component.textfield.TextField;
|
||||
import com.vaadin.flow.data.binder.BeanValidationBinder;
|
||||
import com.vaadin.flow.data.binder.Binder;
|
||||
|
||||
public class EmployeeEditor extends Composite<VerticalLayout> {
|
||||
|
||||
public interface SaveListener {
|
||||
void onSave(Employee employee);
|
||||
}
|
||||
|
||||
public interface DeleteListener {
|
||||
void onDelete(Employee employee);
|
||||
}
|
||||
|
||||
public interface CancelListener {
|
||||
void onCancel();
|
||||
}
|
||||
|
||||
private Employee employee;
|
||||
|
||||
private SaveListener saveListener;
|
||||
private DeleteListener deleteListener;
|
||||
private CancelListener cancelListener;
|
||||
|
||||
private final Binder<Employee> binder = new BeanValidationBinder<>(Employee.class);
|
||||
|
||||
public EmployeeEditor() {
|
||||
var firstName = new TextField("First name");
|
||||
var lastName = new TextField("Last name");
|
||||
|
||||
var save = new Button("Save", VaadinIcon.CHECK.create());
|
||||
var cancel = new Button("Cancel");
|
||||
var delete = new Button("Delete", VaadinIcon.TRASH.create());
|
||||
|
||||
binder.forField(firstName).bind("firstName");
|
||||
binder.forField(lastName).bind("lastName");
|
||||
|
||||
save.addThemeVariants(ButtonVariant.LUMO_PRIMARY);
|
||||
save.addClickListener(e -> save());
|
||||
save.addClickShortcut(Key.ENTER);
|
||||
|
||||
delete.addThemeVariants(ButtonVariant.LUMO_ERROR);
|
||||
delete.addClickListener(e -> deleteListener.onDelete(employee));
|
||||
|
||||
cancel.addClickListener(e -> cancelListener.onCancel());
|
||||
|
||||
getContent().add(firstName, lastName, new HorizontalLayout(save, cancel, delete));
|
||||
}
|
||||
|
||||
private void save() {
|
||||
// Save the form into a new instance of Employee
|
||||
var updated = new Employee();
|
||||
updated.setId(employee.getId());
|
||||
|
||||
if (binder.writeBeanIfValid(updated)) {
|
||||
saveListener.onSave(updated);
|
||||
}
|
||||
}
|
||||
|
||||
public void setEmployee(Employee employee) {
|
||||
this.employee = employee;
|
||||
binder.readBean(employee);
|
||||
}
|
||||
|
||||
public void setSaveListener(SaveListener saveListener) {
|
||||
this.saveListener = saveListener;
|
||||
}
|
||||
|
||||
public void setDeleteListener(DeleteListener deleteListener) {
|
||||
this.deleteListener = deleteListener;
|
||||
}
|
||||
|
||||
public void setCancelListener(CancelListener cancelListener) {
|
||||
this.cancelListener = cancelListener;
|
||||
}
|
||||
}
|
|
@ -0,0 +1,95 @@
|
|||
package com.baeldung.spring;
|
||||
|
||||
import com.baeldung.data.Employee;
|
||||
import com.baeldung.data.EmployeeRepository;
|
||||
|
||||
import com.vaadin.flow.component.button.Button;
|
||||
import com.vaadin.flow.component.grid.Grid;
|
||||
import com.vaadin.flow.component.icon.VaadinIcon;
|
||||
import com.vaadin.flow.component.orderedlayout.HorizontalLayout;
|
||||
import com.vaadin.flow.component.orderedlayout.VerticalLayout;
|
||||
import com.vaadin.flow.component.textfield.TextField;
|
||||
import com.vaadin.flow.data.value.ValueChangeMode;
|
||||
import com.vaadin.flow.router.Route;
|
||||
|
||||
@Route("employees")
|
||||
public class EmployeesView extends VerticalLayout {
|
||||
|
||||
private final EmployeeRepository employeeRepository;
|
||||
|
||||
private final TextField filter;
|
||||
private final Grid<Employee> grid;
|
||||
private final EmployeeEditor editor;
|
||||
|
||||
|
||||
public EmployeesView(EmployeeRepository repo) {
|
||||
employeeRepository = repo;
|
||||
|
||||
// Create components
|
||||
var addButton = new Button("New employee", VaadinIcon.PLUS.create());
|
||||
filter = new TextField();
|
||||
grid = new Grid<>(Employee.class);
|
||||
editor = new EmployeeEditor();
|
||||
|
||||
// Configure components
|
||||
configureEditor();
|
||||
|
||||
addButton.addClickListener(e -> editEmployee(new Employee()));
|
||||
|
||||
filter.setPlaceholder("Filter by last name");
|
||||
filter.setValueChangeMode(ValueChangeMode.LAZY);
|
||||
filter.addValueChangeListener(e -> updateEmployees(e.getValue()));
|
||||
|
||||
grid.setHeight("200px");
|
||||
grid.asSingleSelect().addValueChangeListener(e -> editEmployee(e.getValue()));
|
||||
|
||||
// Compose layout
|
||||
var actionsLayout = new HorizontalLayout(filter, addButton);
|
||||
add(actionsLayout, grid, editor);
|
||||
|
||||
// List customers
|
||||
updateEmployees("");
|
||||
}
|
||||
|
||||
private void configureEditor() {
|
||||
editor.setVisible(false);
|
||||
|
||||
editor.setSaveListener(employee -> {
|
||||
var saved = employeeRepository.save(employee);
|
||||
updateEmployees(filter.getValue());
|
||||
editor.setEmployee(null);
|
||||
grid.asSingleSelect().setValue(saved);
|
||||
});
|
||||
|
||||
editor.setDeleteListener(employee -> {
|
||||
employeeRepository.delete(employee);
|
||||
updateEmployees(filter.getValue());
|
||||
editEmployee(null);
|
||||
});
|
||||
|
||||
editor.setCancelListener(() -> {
|
||||
editEmployee(null);
|
||||
});
|
||||
}
|
||||
|
||||
private void editEmployee(Employee employee) {
|
||||
editor.setEmployee(employee);
|
||||
|
||||
if (employee != null) {
|
||||
editor.setVisible(true);
|
||||
} else {
|
||||
// Deselect grid
|
||||
grid.asSingleSelect().setValue(null);
|
||||
editor.setVisible(false);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
private void updateEmployees(String filterText) {
|
||||
if (filterText.isEmpty()) {
|
||||
grid.setItems(employeeRepository.findAll());
|
||||
} else {
|
||||
grid.setItems(employeeRepository.findByLastNameStartsWithIgnoreCase(filterText));
|
||||
}
|
||||
}
|
||||
}
|
|
@ -1,7 +0,0 @@
|
|||
/* This file is automatically managed and will be overwritten from time to time. */
|
||||
/* Do not manually edit this file. */
|
||||
|
||||
/* Import and include this mixin into your project theme to include the addon themes */
|
||||
@mixin addons {
|
||||
}
|
||||
|
Binary file not shown.
Before Width: | Height: | Size: 30 KiB |
|
@ -1,38 +0,0 @@
|
|||
// If you edit this file you need to compile the theme. See README.md for details.
|
||||
|
||||
// Global variable overrides. Must be declared before importing Valo.
|
||||
|
||||
// Defines the plaintext font size, weight and family. Font size affects general component sizing.
|
||||
//$v-font-size: 16px;
|
||||
//$v-font-weight: 300;
|
||||
//$v-font-family: "Open Sans", sans-serif;
|
||||
|
||||
// Defines the border used by all components.
|
||||
//$v-border: 1px solid (v-shade 0.7);
|
||||
//$v-border-radius: 4px;
|
||||
|
||||
// Affects the color of some component elements, e.g Button, Panel title, etc
|
||||
//$v-background-color: hsl(210, 0%, 98%);
|
||||
// Affects the color of content areas, e.g Panel and Window content, TextField input etc
|
||||
//$v-app-background-color: $v-background-color;
|
||||
|
||||
// Affects the visual appearance of all components
|
||||
//$v-gradient: v-linear 8%;
|
||||
//$v-bevel-depth: 30%;
|
||||
//$v-shadow-opacity: 5%;
|
||||
|
||||
// Defines colors for indicating status (focus, success, failure)
|
||||
//$v-focus-color: valo-focus-color(); // Calculates a suitable color automatically
|
||||
//$v-friendly-color: #2c9720;
|
||||
//$v-error-indicator-color: #ed473b;
|
||||
|
||||
// For more information, see: https://vaadin.com/book/-/page/themes.valo.html
|
||||
// Example variants can be copy/pasted from https://vaadin.com/wiki/-/wiki/Main/Valo+Examples
|
||||
|
||||
@import "../valo/valo.scss";
|
||||
|
||||
@mixin mytheme {
|
||||
@include valo;
|
||||
|
||||
// Insert your own theme rules here
|
||||
}
|
|
@ -1,11 +0,0 @@
|
|||
@import "mytheme.scss";
|
||||
@import "addons.scss";
|
||||
|
||||
// This file prefixes all rules with the theme name to avoid causing conflicts with other themes.
|
||||
// The actual styles should be defined in mytheme.scss
|
||||
|
||||
.mytheme {
|
||||
@include addons;
|
||||
@include mytheme;
|
||||
|
||||
}
|
Loading…
Reference in New Issue