Change-Id: If9299da4415f3181d59b8384e5ac96f940bd5229tags/7.7.0.alpha1
sources for more information about cross-site scripting. | sources for more information about cross-site scripting. | ||||
Offensive code can easily be injected with [literal]#++<script>++# markup or in | Offensive code can easily be injected with [literal]#++<script>++# markup or in | ||||
tag attributes as events, such as | |||||
[parameter]#onLoad#.//// | |||||
TODO Consider an example, Alice, Bob, | |||||
etc. | |||||
//// | |||||
tag attributes as events, such as [parameter]#onLoad#. | |||||
// TODO Consider an example, Alice, Bob, etc. | |||||
Cross-site scripting vulnerabilities are browser dependent, depending on the | Cross-site scripting vulnerabilities are browser dependent, depending on the | ||||
situations in which different browsers execute scripting markup. | situations in which different browsers execute scripting markup. | ||||
component is to allow input of formatted text, you can not just remove all HTML | component is to allow input of formatted text, you can not just remove all HTML | ||||
tags. Also many attributes, such as [parameter]#style#, should pass through the | tags. Also many attributes, such as [parameter]#style#, should pass through the | ||||
sanitization. | sanitization. | ||||
[subs="normal"] | [subs="normal"] | ||||
---- | ---- | ||||
<dependency org="com.vaadin" name="vaadin-spring" | <dependency org="com.vaadin" name="vaadin-spring" | ||||
rev="[replaceable]#latest.release#"/> | |||||
rev="[replaceable]##latest.release##"/> | |||||
---- | ---- | ||||
The Maven dependency is as follows: | The Maven dependency is as follows: | ||||
<dependency> | <dependency> | ||||
<groupId>com.vaadin</groupId> | <groupId>com.vaadin</groupId> | ||||
<artifactId>vaadin-spring</artifactId> | <artifactId>vaadin-spring</artifactId> | ||||
<version>[replaceable]#LATEST#</version> | |||||
<version>[replaceable]##LATEST##</version> | |||||
</dependency> | </dependency> | ||||
---- | ---- | ||||
[[advanced.spring.peparing]] | |||||
[[advanced.spring.preparing]] | |||||
== Preparing Application for Spring | == Preparing Application for Spring | ||||
A Vaadin application that uses Spring must have a file named | A Vaadin application that uses Spring must have a file named | ||||
[filename]#applicationContext.xml# in the [filename]#WEB-INF# directory. | [filename]#applicationContext.xml# in the [filename]#WEB-INF# directory. | ||||
[subs="normal"] | |||||
[subs="verbatim,replacements,quotes"] | |||||
---- | ---- | ||||
<?xml version="1.0" encoding="UTF-8"?> | <?xml version="1.0" encoding="UTF-8"?> | ||||
<beans xmlns="http://www.springframework.org/schema/beans" | <beans xmlns="http://www.springframework.org/schema/beans" | ||||
http://www.springframework.org/schema/context | http://www.springframework.org/schema/context | ||||
http://www.springframework.org/schema/context/spring-context-4.1.xsd"> | http://www.springframework.org/schema/context/spring-context-4.1.xsd"> | ||||
//Configuration object | |||||
<!-- Configuration object --> | |||||
<bean class="[replaceable]#com.example.myapp.MySpringUI.MyConfiguration#" /> | <bean class="[replaceable]#com.example.myapp.MySpringUI.MyConfiguration#" /> | ||||
//Location for automatically scanned beans | |||||
<!-- Location for automatically scanned beans --> | |||||
<context:component-scan | <context:component-scan | ||||
base-package="[replaceable]#com.example.myapp.domain#" /> | base-package="[replaceable]#com.example.myapp.domain#" /> | ||||
</beans> | </beans> | ||||
public class MySpringUI extends UI { | public class MySpringUI extends UI { | ||||
@Autowired | @Autowired | ||||
SpringViewProvider viewProvider; | SpringViewProvider viewProvider; | ||||
@Override | @Override | ||||
protected void init(VaadinRequest request) { | protected void init(VaadinRequest request) { | ||||
Navigator navigator = new Navigator(this, this); | Navigator navigator = new Navigator(this, this); | ||||
@SpringView(name="myview", uis={UI.class}) | @SpringView(name="myview", uis={UI.class}) | ||||
---- | ---- | ||||
In the following, we have a login view that accesses a session-scoped user | In the following, we have a login view that accesses a session-scoped user | ||||
object. Here, we use a constant to define the view name, so that we can use the | object. Here, we use a constant to define the view name, so that we can use the | ||||
constant when navigating to it. | constant when navigating to it. | ||||
[source, java] | [source, java] | ||||
---- | ---- | ||||
@SpringView(name=LoginView.NAME) | @SpringView(name=LoginView.NAME) | ||||
public class LoginView extends CustomComponent | public class LoginView extends CustomComponent | ||||
implements View { | implements View { | ||||
public final static String NAME = ""; | public final static String NAME = ""; | ||||
// Here we inject to the constructor and actually do | // Here we inject to the constructor and actually do | ||||
// not store the injected object to use it later | // not store the injected object to use it later | ||||
@Autowired | @Autowired | ||||
public LoginView(User user) { | public LoginView(User user) { | ||||
VerticalLayout layout = new VerticalLayout(); | VerticalLayout layout = new VerticalLayout(); | ||||
// An input field for editing injected data | // An input field for editing injected data | ||||
BeanItem<User> item = new BeanItem<User>(user); | BeanItem<User> item = new BeanItem<User>(user); | ||||
TextField username = new TextField("User name", | TextField username = new TextField("User name", | ||||
layout.addComponent(new Button("Login", e -> | layout.addComponent(new Button("Login", e -> | ||||
getUI().getNavigator(). | getUI().getNavigator(). | ||||
navigateTo(MainView.VIEWNAME))); | navigateTo(MainView.VIEWNAME))); | ||||
setCompositionRoot(layout); | setCompositionRoot(layout); | ||||
} | } | ||||
@Override | @Override | ||||
public void enter(ViewChangeEvent event) {} | public void enter(ViewChangeEvent event) {} | ||||
} | } | ||||
You could now navigate to the view from any other view in the UI with: | You could now navigate to the view from any other view in the UI with: | ||||
[source, java] | [source, java] | ||||
---- | ---- | ||||
getUI().getNavigator().navigateTo(LoginView.VIEWNAME); | getUI().getNavigator().navigateTo(LoginView.VIEWNAME); | ||||
---- | ---- | ||||
endif::web[] | endif::web[] | ||||
[[advanced.spring.accesscontrol]] | [[advanced.spring.accesscontrol]] | ||||
---- | ---- | ||||
<web-app> | <web-app> | ||||
... | ... | ||||
<servlet> | <servlet> | ||||
<servlet-name>Default</servlet-name> | <servlet-name>Default</servlet-name> | ||||
<servlet-class> | <servlet-class> | ||||
<servlet-mapping> | <servlet-mapping> | ||||
<servlet-name>Default</servlet-name> | <servlet-name>Default</servlet-name> | ||||
<url-pattern>[replaceable]#/myspringuis/*#</url-pattern> | |||||
<url-pattern>[replaceable]##/myspringuis/*##</url-pattern> | |||||
</servlet-mapping> | </servlet-mapping> | ||||
<servlet-mapping> | <servlet-mapping> | ||||
<servlet-name>Default</servlet-name> | <servlet-name>Default</servlet-name> | ||||
<url-pattern>/VAADIN/*</url-pattern> | |||||
<url-pattern>/VAADIN/+++*+++</url-pattern> | |||||
</servlet-mapping> | </servlet-mapping> | ||||
</web-app> | </web-app> | ||||
---- | ---- | ||||
With such a setting, paths to Spring UIs would have base path | |||||
[filename]#/myapp/myspringuis#, to which the (optional) UI path would be | |||||
appended. The [filename]#/VAADIN/*# only needs to be mapped to the servlet if | |||||
there are no other Vaadin servlets. | |||||
With such a setting, paths to Spring UIs would have base path [filename]#/myapp/myspringuis#, to which the (optional) UI path would be appended. | |||||
The [filename]#/VAADIN/*# only needs to be mapped to the servlet if there are no other Vaadin servlets. | |||||
(((range="endofrange", startref="term.advanced.spring.springlong"))) | (((range="endofrange", startref="term.advanced.spring.springlong"))) | ||||
(((range="endofrange", startref="term.advanced.spring.spring"))) | (((range="endofrange", startref="term.advanced.spring.spring"))) | ||||
Because of the special nature of AJAX applications, use of multiple windows uses | Because of the special nature of AJAX applications, use of multiple windows uses | ||||
require some | require some | ||||
caveats.//// | |||||
caveats. | |||||
//// | |||||
TODO Re-enable We will go through them later in <xref | TODO Re-enable We will go through them later in <xref | ||||
linkend="advanced.windows.caveats"/>. | linkend="advanced.windows.caveats"/>. | ||||
//// | //// | ||||
@Override | @Override | ||||
protected void init(VaadinRequest request) { | protected void init(VaadinRequest request) { | ||||
getPage().setTitle("Popup Window"); | getPage().setTitle("Popup Window"); | ||||
// Have some content for it | // Have some content for it | ||||
VerticalLayout content = new VerticalLayout(); | VerticalLayout content = new VerticalLayout(); | ||||
Label label = | Label label = | ||||
window features, as defined in the HTML specification. | window features, as defined in the HTML specification. | ||||
status=[parameter]#0|1#:: Whether the status bar at the bottom of the window should be enabled. | status=[parameter]#0|1#:: Whether the status bar at the bottom of the window should be enabled. | ||||
[parameter]##:: | |||||
[parameter]##:: | |||||
scrollbars:: Enables scrollbars in the window if the document area is bigger than the view area of the window. | scrollbars:: Enables scrollbars in the window if the document area is bigger than the view area of the window. | ||||
resizable:: Allows the user to resize the browser window (no effect for tabs). | resizable:: Allows the user to resize the browser window (no effect for tabs). | ||||
menubar:: Enables the browser menu bar. | menubar:: Enables the browser menu bar. | ||||
} | } | ||||
} | } | ||||
---- | ---- | ||||
[parameter]#UI# parameter for the [classname]#com.vaadin.server.VaadinServlet#. | [parameter]#UI# parameter for the [classname]#com.vaadin.server.VaadinServlet#. | ||||
The servlet is then mapped to a URL path in a standard way for Java Servlets. | The servlet is then mapped to a URL path in a standard way for Java Servlets. | ||||
[subs="normal"] | |||||
[subs="verbatim,replacements,quotes"] | |||||
---- | ---- | ||||
<?xml version="1.0" encoding="UTF-8"?> | <?xml version="1.0" encoding="UTF-8"?> | ||||
<web-app | <web-app | ||||
id="WebApp_ID" version="2.4" | id="WebApp_ID" version="2.4" | ||||
xmlns="http://java.sun.com/xml/ns/j2ee" | |||||
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" | |||||
xmlns="http://java.sun.com/xml/ns/j2ee" | |||||
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" | |||||
xsi:schemaLocation="http://java.sun.com/xml/ns/j2ee | xsi:schemaLocation="http://java.sun.com/xml/ns/j2ee | ||||
http://java.sun.com/xml/ns/j2ee/web-app_2_4.xsd"> | http://java.sun.com/xml/ns/j2ee/web-app_2_4.xsd"> | ||||
<servlet> | <servlet> | ||||
<servlet-name>**myservlet**</servlet-name> | |||||
<servlet-name>[replaceable]##myservlet##</servlet-name> | |||||
<servlet-class> | <servlet-class> | ||||
com.vaadin.server.VaadinServlet | |||||
[replaceable]##com.vaadin.server.VaadinServlet## | |||||
</servlet-class> | </servlet-class> | ||||
<init-param> | <init-param> | ||||
<param-name>UI</param-name> | <param-name>UI</param-name> | ||||
<param-value>**com.ex.myprj.MyUI**</param-value> | |||||
<param-value>[replaceable]##com.ex.myprj.MyUI##</param-value> | |||||
</init-param> | </init-param> | ||||
<!-- If not using the default widget set--> | <!-- If not using the default widget set--> | ||||
<init-param> | <init-param> | ||||
<param-name>widgetset</param-name> | <param-name>widgetset</param-name> | ||||
<param-value>**com.ex.myprj.MyWidgetSet**</param-value> | |||||
<param-value>[replaceable]##com.ex.myprj.MyWidgetSet##</param-value> | |||||
</init-param> | </init-param> | ||||
</servlet> | </servlet> | ||||
<servlet-mapping> | <servlet-mapping> | ||||
<servlet-name>**myservlet**</servlet-name> | |||||
<url-pattern>/*</url-pattern> | |||||
<servlet-name>[replaceable]##myservlet##</servlet-name> | |||||
<url-pattern>[replaceable]##/*##</url-pattern> | |||||
</servlet-mapping> | </servlet-mapping> | ||||
</web-app> | </web-app> | ||||
---- | ---- | ||||
---- | ---- | ||||
<web-app | <web-app | ||||
id="WebApp_ID" version="**3.0**" | id="WebApp_ID" version="**3.0**" | ||||
xmlns="http://java.sun.com/xml/ns/j2ee" | |||||
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" | |||||
xmlns="http://java.sun.com/xml/ns/j2ee" | |||||
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" | |||||
xsi:schemaLocation="**http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_3_0.xsd**"> | xsi:schemaLocation="**http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_3_0.xsd**"> | ||||
---- | ---- | ||||
Servlet 3.0 support is useful for at least server push. | Servlet 3.0 support is useful for at least server push. | ||||
[classname]#PortletSession# session properties through the interface, such as | [classname]#PortletSession# session properties through the interface, such as | ||||
set and read session attributes that are shared by all servlets belonging to a | set and read session attributes that are shared by all servlets belonging to a | ||||
particular servlet or portlet session. | particular servlet or portlet session. | ||||
[[figure.application.errors.error-indicator]] | [[figure.application.errors.error-indicator]] | ||||
.Error Indicator Active | .Error Indicator Active | ||||
image::img/errorindicator-example2.png[] | |||||
image::img/errorindicator-example2.png[scaledwidth=40%] | |||||
[[application.errors.reconnect]] | [[application.errors.reconnect]] | ||||
== Connection Fault | == Connection Fault | ||||
---- | ---- | ||||
getService().setSystemMessagesProvider( | getService().setSystemMessagesProvider( | ||||
new SystemMessagesProvider() { | new SystemMessagesProvider() { | ||||
@Override | |||||
@Override | |||||
public SystemMessages getSystemMessages( | public SystemMessages getSystemMessages( | ||||
SystemMessagesInfo systemMessagesInfo) { | SystemMessagesInfo systemMessagesInfo) { | ||||
CustomizedSystemMessages messages = | CustomizedSystemMessages messages = | ||||
ifdef::web[] | ifdef::web[] | ||||
[[application.errors.unchecked-exceptions]] | [[application.errors.unchecked-exceptions]] | ||||
== Handling Uncaught Exceptions | |||||
== Handling Uncaught Exceptions | |||||
Handling events can result in exceptions either in the application logic or in | Handling events can result in exceptions either in the application logic or in | ||||
the framework itself, but some of them may not be caught properly by the | the framework itself, but some of them may not be caught properly by the | ||||
[source, java] | [source, java] | ||||
---- | ---- | ||||
// Here's some code that produces an uncaught exception | |||||
// Here's some code that produces an uncaught exception | |||||
final VerticalLayout layout = new VerticalLayout(); | final VerticalLayout layout = new VerticalLayout(); | ||||
final Button button = new Button("Click Me!", | final Button button = new Button("Click Me!", | ||||
new Button.ClickListener() { | new Button.ClickListener() { | ||||
t = t.getCause()) | t = t.getCause()) | ||||
if (t.getCause() == null) // We're at final cause | if (t.getCause() == null) // We're at final cause | ||||
cause += t.getClass().getName() + "<br/>"; | cause += t.getClass().getName() + "<br/>"; | ||||
// Display the error message in a custom fashion | // Display the error message in a custom fashion | ||||
layout.addComponent(new Label(cause, ContentMode.HTML)); | layout.addComponent(new Label(cause, ContentMode.HTML)); | ||||
// Do the default error handling (optional) | // Do the default error handling (optional) | ||||
doDefault(event); | doDefault(event); | ||||
} | |||||
} | |||||
}); | }); | ||||
---- | ---- | ||||
error. If the error is not associated with a component, it returns null. | error. If the error is not associated with a component, it returns null. | ||||
endif::web[] | endif::web[] | ||||
[[preface]] | |||||
[preface] | |||||
[] | |||||
== Preface | |||||
This book provides an overview of the Vaadin Framework and covers the most | |||||
important topics that you might encounter while developing applications with it. | |||||
A more detailed documentation of the individual classes, interfaces, and methods | |||||
is given in the Vaadin API Reference. | |||||
This edition mostly covers Vaadin Framework 7.5 released in 2015, as well as the | |||||
latest versions of Vaadin Pro Tools. In addition to updates in the core | |||||
framework, the Volume 1 includes a new chapter about the new Vaadin Designer | |||||
plugin for Eclipse. New add-ons, namely Vaadin Spreadsheet, Vaadin CDI, and | |||||
Vaadin Spring, which were released earlier this year, are documented in Volume | |||||
2. | |||||
Writing this manual is an ongoing work and it is rarely completely up-to-date | |||||
with the quick-evolving product. Some features may not be included in this book | |||||
yet. For the most current version, please see the on-line edition available at | |||||
http://vaadin.com/book. You can also find PDF and EPUB versions of the book | |||||
there. You may find the other versions more easily searchable than the printed | |||||
book. The index in the book is incomplete and will be expanded later. The web | |||||
edition also has some additional technical content, such as some example code | |||||
and additional sections that you may need when actually doing development. The | |||||
purpose of the slightly abridged print edition is more to be an introductionary | |||||
textbook to Vaadin, and still fit in your pocket. | |||||
Also, many Vaadin 7 features are showcased as mini-tutorials, which are | |||||
available in the Vaadin Wiki at https://vaadin.com/wiki/-/wiki/Main/Vaadin+7. | |||||
= Who is This Book For? | |||||
This book is intended for software developers who use, or are considering to | |||||
use, Vaadin to develop web applications. | |||||
The book assumes that you have some experience with programming in Java, but if | |||||
not, it is at least as easy to begin learning Java with Vaadin as with any other | |||||
UI framework. No knowledge of AJAX is needed as it is well hidden from the | |||||
developer. | |||||
You may have used some desktop-oriented user interface frameworks for Java, such | |||||
as AWT, Swing, or SWT, or a library such as Qt for C++. Such knowledge is useful | |||||
for understanding the scope of Vaadin, the event-driven programming model, and | |||||
other common concepts of UI frameworks, but not necessary. | |||||
If you do not have a web graphics designer at hand, knowing the basics of HTML | |||||
and CSS can help so that you can develop presentation themes for your | |||||
application. A brief introduction to CSS is provided. Knowledge of Google Web | |||||
Toolkit (GWT) may be useful if you develop or integrate new client-side | |||||
components. | |||||
= Organization of This Book | |||||
The Book of Vaadin gives an introduction to what Vaadin is and how you use it to | |||||
develop web applications. | |||||
Volume 1 | |||||
<<dummy/../../../framework/introduction/introduction-overview.asciidoc#intro.overview,"Introduction">>:: The chapter gives an introduction to the application architecture supported by | |||||
Vaadin, the core design ideas behind the framework, and some historical | |||||
background. | |||||
<<dummy/../../../framework/getting-started/getting-started-overview.asciidoc#getting-started.overview,"Getting Started with Vaadin">>:: This chapter gives practical instructions for installing Vaadin and the | |||||
reference toolchain, including the Vaadin Plugin for Eclipse, how to run and | |||||
debug the demos, and how to create your own application project in the Eclipse | |||||
IDE. | |||||
<<dummy/../../../framework/architecture/architecture-overview.asciidoc#architecture.overview,"Architecture">>:: This chapter gives an introduction to the architecture of Vaadin and its major | |||||
technologies, including AJAX, Google Web Toolkit, and event-driven programming. | |||||
<<dummy/../../../framework/application/application-overview.asciidoc#application.overview,"Writing a Server-Side Web Application">>:: This chapter gives all the practical knowledge required for creating | |||||
applications with Vaadin, such as window management, application lifecycle, | |||||
deployment in a servlet container, and handling events, errors, and resources. | |||||
<<dummy/../../../framework/components/components-overview.asciidoc#components.overview,"User Interface Components">>:: This chapter gives the basic usage documentation for all the (non-layout) user | |||||
interface components in Vaadin and their most significant features. The | |||||
component sections include examples for using each component, as well as for | |||||
styling with CSS/Sass. | |||||
<<dummy/../../../framework/layout/layout-overview.asciidoc#layout.overview,"Managing Layout">>:: This chapter describes the layout components, which are used for managing the | |||||
layout of the user interface, just like in any desktop application frameworks. | |||||
<<dummy/../../../designer/designer-overview.asciidoc#designer.overview,"Vaadin Designer">>:: This chapter gives instructions for using Vaadin Designer, a visual tool for the | |||||
Eclipse IDE for creating composite designs, such as for UIs, views, or other | |||||
composites. | |||||
Volume 2: | |||||
<<dummy/../../../framework/themes/themes-overview.asciidoc#themes.overview,"Themes">>:: This chapter gives an introduction to Cascading Style Sheets (CSS) and Sass and | |||||
explains how you can use them to build custom visual themes for your | |||||
application. | |||||
<<dummy/../../../framework/datamodel/datamodel-overview.asciidoc#datamodel.overview,"Binding Components to Data">>:: This chapter gives an overview of the built-in data model of Vaadin, consisting | |||||
of properties, items, and containers. | |||||
<<dummy/../../../framework/sqlcontainer/sqlcontainer-overview.asciidoc#sqlcontainer.overview,"Vaadin SQLContainer">>:: This chapter gives documentation for the SQLContainer, which allows binding | |||||
Vaadin components to SQL queries. | |||||
<<dummy/../../../framework/advanced/advanced-overview.asciidoc#advanced.overview,"Advanced Web Application Topics">>:: This chapter provides many special topics that are commonly needed in | |||||
applications, such as opening new browser windows, embedding applications in | |||||
regular web pages, low-level management of resources, shortcut keys, debugging, | |||||
etc. | |||||
<<dummy/../../../framework/portal/portal-overview.asciidoc#portal.overview,"Portal Integration">>:: This chapter describes the development of Vaadin applications as portlets which | |||||
you can deploy to any portal supporting Java Portlet API 2.0 (JSR-286). The | |||||
chapter also describes the special support for Liferay and the Control Panel, | |||||
IPC, and WSRP add-ons. | |||||
<<dummy/../../../framework/clientside/clientside-overview.asciidoc#clientside.overview,"Client-Side Vaadin Development">>:: This chapter gives an introduction to creating and developing client-side | |||||
applications and widgets, including installation, compilation, and debugging. | |||||
<<dummy/../../../framework/clientsideapp/clientsideapp-overview.asciidoc#clientsideapp.overview,"Client-Side Applications">>:: This chapter describes how to develop client-side applications and how to | |||||
integrate them with a back-end service. | |||||
<<dummy/../../../framework/clientsidewidgets/clientsidewidgets-overview.asciidoc#clientsidewidgets.overview,"Client-Side Widgets">>:: This chapter describes the built-in widgets (client-side components) available | |||||
for client-side development. The built-in widgets include Google Web Toolkit | |||||
widgets as well as Vaadin widgets. | |||||
<<dummy/../../../framework/gwt/gwt-overview.asciidoc#gwt.overview,"Integrating with the Server-Side">>:: This chapter describes how to integrate client-side widgets with their | |||||
server-side counterparts for the purpose of creating new server-side components. | |||||
The chapter also covers integrating JavaScript components. | |||||
<<dummy/../../../framework/addons/addons-overview.asciidoc#addons.overview,"Using Vaadin Add-ons">>:: This chapter gives instructions for downloading and installing add-on components | |||||
from the Vaadin Directory. | |||||
<<dummy/../../../charts/charts-overview.asciidoc#charts.overview,"Vaadin Charts">>:: This chapter documents the use of the Vaadin Charts add-on component for | |||||
interactive charting with many diagram types. The add-on includes the Chart and | |||||
Timeline components. | |||||
<<dummy/../../../framework/jpacontainer/jpacontainer-overview.asciidoc#jpacontainer.overview,"Vaadin JPAContainer">>:: This chapter gives documentation of the JPAContainer add-on, which allows | |||||
binding Vaadin components directly to relational and other databases using Java | |||||
Persistence API (JPA). | |||||
<<dummy/../../../mobile/mobile-overview.asciidoc#mobile.overview,"Mobile Applications with TouchKit">>:: This chapter gives examples and reference documentation for using the Vaadin | |||||
TouchKit add-on for developing mobile applications. | |||||
<<dummy/../../../spreadsheet/spreadsheet-overview.asciidoc#spreadsheet.overview,"Vaadin Spreadsheet">>:: This chapter gives documentation of the Vaadin Spreadsheet add-on, which | |||||
provides a Microsoft Excel compatible spreadsheet component. | |||||
<<dummy/../../../testbench/testbench-overview.asciidoc#testbench.overview,"Vaadin TestBench">>:: This chapter gives the complete documentation of using the Vaadin TestBench tool | |||||
for recording and executing user interface regression tests of Vaadin | |||||
applications. | |||||
= Supplementary Material | |||||
The Vaadin websites offer plenty of material that can help you understand what | |||||
Vaadin is, what you can do with it, and how you can do it. | |||||
Demo Applications:: The most important demo application for Vaadin is the Sampler, which | |||||
demonstrates the use of all basic components and features. You can run it | |||||
on-line at http://demo.vaadin.com/ or download it as a WAR from the | |||||
link:http://vaadin.com/download/[Vaadin download page]. | |||||
+ | |||||
Most of the code examples in this book and many others can be found online at | |||||
http://demo.vaadin.com/book-examples-vaadin7/book/. | |||||
Cheat Sheet:: The two-page cheat sheet illustrates the basic relationship hierarchy of the | |||||
user interface and data binding classes and interfaces. You can download it at | |||||
http://vaadin.com/book. | |||||
Refcard:: The six-page DZone Refcard gives an overview to application development with | |||||
Vaadin. It includes a diagram of the user interface and data binding classes and | |||||
interfaces. You can find more information about it at | |||||
https://vaadin.com/refcard. | |||||
Address Book Tutorial:: The Address Book is a sample application accompanied with a tutorial that gives | |||||
detailed step-by-step instructions for creating a real-life web application with | |||||
Vaadin. You can find the tutorial from the product website. | |||||
Developer's Website:: Vaadin Developer's Site at http://dev.vaadin.com/ provides various online | |||||
resources, such as the ticket system, a development wiki, source repositories, | |||||
activity timeline, development milestones, and so on. | |||||
+ | |||||
The wiki provides instructions for developers, especially for those who wish to | |||||
check-out and compile Vaadin itself from the source repository. The technical | |||||
articles deal with integration of Vaadin applications with various systems, such | |||||
as JSP, Maven, Spring, Hibernate, and portals. The wiki also provides answers to | |||||
Frequently Asked Questions. | |||||
Online Documentation:: You can read this book online at http://vaadin.com/book. Lots of additional | |||||
material, including technical HOWTOs, answers to Frequently Asked Questions and | |||||
other documentation is also available on link:http://dev.vaadin.com/[Vaadin | |||||
web-site]. | |||||
= Support | |||||
Stuck with a problem? No need to lose your hair over it, the Vaadin Framework | |||||
developer community and the Vaadin company offer support to all of your needs. | |||||
Community Support Forum:: You can find the user and developer community forum at http://vaadin.com/forum. | |||||
Please use the forum to discuss any problems you might encounter, wishes for | |||||
features, and so on. The answer to your problems may already lie in the forum | |||||
archives, so searching the discussions is always the best way to begin. | |||||
Report Bugs:: If you have found a possible bug in Vaadin, the demo applications, or the | |||||
documentation, please report it by filing a ticket at the Vaadin developer's | |||||
site at http://dev.vaadin.com/. You may want to check the existing tickets | |||||
before filing a new one. You can make a ticket to make a request for a new | |||||
feature as well, or to suggest modifications to an existing feature. | |||||
Commercial Support:: Vaadin offers full commercial support and training services for the Vaadin | |||||
Framework and related products. Read more about the commercial products at | |||||
http://vaadin.com/pro for details. | |||||
= About the Author | |||||
Marko Grönroos is a professional writer and software developer working at Vaadin | |||||
Ltd in Turku, Finland. He has been involved in web application development since | |||||
1994 and has worked on several application development frameworks in C, C++, and | |||||
Java. He has been active in many open source software projects and holds an | |||||
M.Sc. degree in Computer Science from the University of Turku. | |||||
= Acknowledgements | |||||
Much of the book is the result of close work within the development team at | |||||
Vaadin Ltd. Joonas Lehtinen, CEO of Vaadin Ltd, wrote the first outline of the | |||||
book, which became the basis for the first two chapters. Since then, Marko | |||||
Grönroos has become the primary author and editor. The development team has | |||||
contributed several passages, answered numerous technical questions, reviewed | |||||
the manual, and made many corrections. | |||||
The contributors are (in rough chronological order): | |||||
[options="compact"] | |||||
* Joonas Lehtinen | |||||
* Jani Laakso | |||||
* Marko Grönroos | |||||
* Jouni Koivuviita | |||||
* Matti Tahvonen | |||||
* Artur Signell | |||||
* Marc Englund | |||||
* Henri Sara | |||||
* Jonatan Kronqvist | |||||
* Mikael Grankvist (TestBench) | |||||
* Teppo Kurki (SQLContainer) | |||||
* Tomi Virtanen (Calendar) | |||||
* Risto Yrjänä (Calendar) | |||||
* John Ahlroos (Timeline) | |||||
* Petter Holmström (JPAContainer) | |||||
* Leif Åstrand | |||||
* Guillermo Alvarez (Charts) | |||||
= About Vaadin Ltd | |||||
Vaadin Ltd is a Finnish software company specializing in the design and | |||||
development of Rich Internet Applications. The company offers planning, | |||||
implementation, and support services for the software projects of its customers, | |||||
as well as sub-contract software development. Vaadin Framework, previously known | |||||
as IT Mill Toolkit, is the flagship open source product of the company, for | |||||
which it provides commercial development and support services. | |||||
//====================================================================== | |||||
//Copyright 2000-2012 Vaadin Ltd | |||||
//All Rights Reserved | |||||
//This work is licensed under a Creative Commons Attribution-NoDerivs | |||||
//License (CC-BY-ND) Version 3.0. Full license text is available at: | |||||
//http://creativecommons.org/licenses/by-nd/3.0/legalcode | |||||
//====================================================================== | |||||
//The Doctype definition must be exactly same for book-pocket.pdf | |||||
:experimental: true | |||||
:source-highlighter: coderay | |||||
Book of VaadinVaadin 7 Edition - 6th Revision | |||||
MarkoGrönroos | |||||
Tracy | |||||
Translator | |||||
Translation | |||||
This book can be downloaded for free at | |||||
http://vaadin.com/book | |||||
Vaadin Ltd | |||||
Vaadin Ltd | |||||
Ruukinkatu 2-4 | |||||
20540 | |||||
Turku | |||||
Finland | |||||
2012-02-29Vaadin Framework | |||||
Vaadin Framework | |||||
7.4 | |||||
Vaadin 7 Edition - 6th Revision | |||||
Bookwell Oy | |||||
Juva | |||||
Finland | |||||
2000-2015Vaadin Ltd | |||||
All rights reserved. This work is licensed under the Creative Commons CC-BY-ND | |||||
License Version 2.0. | |||||
Vaadin is an AJAX web application development framework that enables | |||||
developers to build high-quality user interfaces with Java, both on the | |||||
server- and client-side. It provides a set of libraries of ready-to-use user | |||||
interface components and a clean framework for creating your own | |||||
components. The focus is on ease-of-use, re-usability, extensibility, and | |||||
meeting the requirements of large enterprise applications. | |||||
include::book-preface.asciidoc[] | |||||
include::introduction/chapter-introduction.asciidoc[] | |||||
include::getting-started/chapter-getting-started.asciidoc[] | |||||
include::architecture/chapter-architecture.asciidoc[] | |||||
include::application/chapter-application.asciidoc[] | |||||
include::components/chapter-components.asciidoc[] | |||||
include::layout/chapter-layout.asciidoc[] | |||||
include::designer/chapter-designer.asciidoc[] | |||||
include::themes/chapter-themes.asciidoc[] | |||||
include::datamodel/chapter-datamodel.asciidoc[] | |||||
include::sqlcontainer/chapter-sqlcontainer.asciidoc[] | |||||
include::advanced/chapter-advanced.asciidoc[] | |||||
include::portal/chapter-portal.asciidoc[] | |||||
include::clientside/chapter-clientside.asciidoc[] | |||||
include::clientsideapp/chapter-clientsideapp.asciidoc[] | |||||
include::clientsidewidgets/chapter-clientsidewidgets.asciidoc[] | |||||
include::gwt/chapter-gwt.asciidoc[] | |||||
include::addons/chapter-addons.asciidoc[] | |||||
include::charts/chapter-charts.asciidoc[] | |||||
include::jpacontainer/chapter-jpacontainer.asciidoc[] | |||||
include::mobile/chapter-mobile.asciidoc[] | |||||
include::spreadsheet/chapter-spreadsheet.asciidoc[] | |||||
include::testbench/chapter-testbench.asciidoc[] | |||||
include::index.asciidoc[]//// | |||||
Keep this comment at the end of the file Local variables: mode: xml sgml-omittag:nil sgml-shorttag:nil sgml-namecase-general:nil sgml-general-insert-case:lower sgml-minimize-attributes:nil sgml-always-quote-attributes:t sgml-indent-step:4 sgml-indent-data:t sgml-parent-document:nil sgml-exposed-tags:nil sgml-local-catalogs:("/etc/sgml/catalog" "/usr/share/xemacs21/xemacs-packages/etc/psgml-dtds/CATALOG") sgml-local-ecat-files:("ECAT" "~/sgml/ECAT" "/usr/share/sgml/ECAT" "/usr/local/share/sgml/ECAT" "/usr/local/lib/sgml/ECAT") End: | |||||
//// |
As most Vaadin add-ons include widgets, widget set compilation is usually needed | As most Vaadin add-ons include widgets, widget set compilation is usually needed | ||||
when using add-ons. In that case, the widget sets from different add-ons are | when using add-ons. In that case, the widget sets from different add-ons are | ||||
compiled into a __project widget set__, as described in | compiled into a __project widget set__, as described in | ||||
<<dummy/../../../framework/addons/addons-overview.asciidoc#addons.overview,"Using | |||||
Vaadin | |||||
Add-ons">>.//// | |||||
<<dummy/../../../framework/addons/addons-overview.asciidoc#addons.overview,"Using Vaadin Add-ons">>. | |||||
//// | |||||
TODO Provide a link to a proper add-on compilation section when one is | TODO Provide a link to a proper add-on compilation section when one is | ||||
available. | available. | ||||
//// | //// | ||||
---- | ---- | ||||
[prompt]#$# [command]#mvn# [parameter]#vaadin:compile# | [prompt]#$# [command]#mvn# [parameter]#vaadin:compile# | ||||
---- | ---- | ||||
<<dummy/../../../framework/clientsideapp/clientsideapp-loading#clientsideapp.loading,"Loading | <<dummy/../../../framework/clientsideapp/clientsideapp-loading#clientsideapp.loading,"Loading | ||||
a Client-Side Application">>. | a Client-Side Application">>. | ||||
// TODO What is this? What's an "UI Binder"? | |||||
The client-side user interface can be built declaratively using the included | The client-side user interface can be built declaratively using the included | ||||
__UI | |||||
Binder__//// | |||||
, as described in <xref | |||||
linkend="clientsideapp.uibinder"/> | |||||
//// | |||||
. | |||||
__UI Binder__. | |||||
// , as described in <<clientsideapp.uibinder>>. | |||||
The servlet for processing RPC calls from the client-side can be generated | The servlet for processing RPC calls from the client-side can be generated | ||||
automatically using the included compiler. | automatically using the included compiler. | ||||
an off-line mode if the connection is closed. An off-line mode can persist data | an off-line mode if the connection is closed. An off-line mode can persist data | ||||
in a local store in the browser, thereby avoiding the need for server-side | in a local store in the browser, thereby avoiding the need for server-side | ||||
storage, and transmit the data to the server when the connection is again | storage, and transmit the data to the server when the connection is again | ||||
available. Such a pattern is commonly used with Vaadin | |||||
TouchKit.//// | |||||
Use of a client-side application to provide an off-line mode is described in | |||||
<xref | |||||
linkend="clientsideapp.offline"/>. | |||||
//// | |||||
available. Such a pattern is commonly used with Vaadin TouchKit. | |||||
//// | |||||
TODO It may be necessary to have such a section at some point. | |||||
Use of a client-side application to provide an off-line mode is described in <<clientsideapp.offline>>. | |||||
//// |
// Use a container of built-in BasicEvents | // Use a container of built-in BasicEvents | ||||
final BeanItemContainer<BasicEvent> container = | final BeanItemContainer<BasicEvent> container = | ||||
new BeanItemContainer<BasicEvent>(BasicEvent.class); | |||||
new BeanItemContainer<BasicEvent>(BasicEvent.class); | |||||
// Create a meeting in the container | // Create a meeting in the container | ||||
container.addBean(new BasicEvent("The Event", "Single Event", | container.addBean(new BasicEvent("The Event", "Single Event", | ||||
// Set the container as the data source | // Set the container as the data source | ||||
calendar.setEventProvider(cep); | calendar.setEventProvider(cep); | ||||
// Now we can add events to the database through the calendar | // Now we can add events to the database through the calendar | ||||
BasicEvent event = new BasicEvent("The Event", "Single Event", | BasicEvent event = new BasicEvent("The Event", "Single Event", | ||||
new GregorianCalendar(2012,1,15,12,00).getTime(), | new GregorianCalendar(2012,1,15,12,00).getTime(), | ||||
EventChangeListener listener) { | EventChangeListener listener) { | ||||
... | ... | ||||
} | } | ||||
public void removeListener(EventChangeListener listener) { | public void removeListener(EventChangeListener listener) { | ||||
... | ... | ||||
} | } | ||||
Calendar calendar = new Calendar(); | Calendar calendar = new Calendar(); | ||||
calendar.setDropHandler(new DropHandler() { | calendar.setDropHandler(new DropHandler() { | ||||
public void drop(DragAndDropEvent event) { | public void drop(DragAndDropEvent event) { | ||||
CalendarTargetDetails details = | |||||
CalendarTargetDetails details = | |||||
(CalendarTargetDetails) event.getTargetDetails(); | (CalendarTargetDetails) event.getTargetDetails(); | ||||
TableTransferable transferable = | |||||
TableTransferable transferable = | |||||
(TableTransferable) event.getTransferable(); | (TableTransferable) event.getTransferable(); | ||||
createEvent(details, transferable); | createEvent(details, transferable); | ||||
Vaadin Calendar has only limited built-in navigation support. The weekly view | Vaadin Calendar has only limited built-in navigation support. The weekly view | ||||
has navigation buttons in the top left and top right | has navigation buttons in the top left and top right | ||||
corners.//// | |||||
TODO See the figure | |||||
4. | |||||
//// | |||||
corners. | |||||
// TODO See the figure 4. | |||||
You can handle backward and forward navigation with a | You can handle backward and forward navigation with a | ||||
[interfacename]#BackwardListener# and [interfacename]#ForwardListener#. | [interfacename]#BackwardListener# and [interfacename]#ForwardListener#. | ||||
[source, java] | [source, java] | ||||
---- | ---- | ||||
cal.setHandler(new BasicBackwardHandler() { | cal.setHandler(new BasicBackwardHandler() { | ||||
java.util.Calendar calendar = event.getComponent() | java.util.Calendar calendar = event.getComponent() | ||||
.getInternalCalendar(); | .getInternalCalendar(); | ||||
if (isThisYear(calendar, end) | |||||
if (isThisYear(calendar, end) | |||||
&& isThisYear(calendar, start)) { | && isThisYear(calendar, start)) { | ||||
super.setDates(event, start, end); | super.setDates(event, start, end); | ||||
} | } | ||||
calendar.setHandler(new BasicDateClickHandler() { | calendar.setHandler(new BasicDateClickHandler() { | ||||
public void dateClick(DateClickEvent event) { | public void dateClick(DateClickEvent event) { | ||||
Calendar cal = event.getComponent(); | Calendar cal = event.getComponent(); | ||||
// Check if the current range is already one day long | // Check if the current range is already one day long | ||||
long currentCalDateRange = cal.getEndDate().getTime() - | long currentCalDateRange = cal.getEndDate().getTime() - | ||||
cal.getStartDate().getTime(); | cal.getStartDate().getTime(); | ||||
Date start, Date end) { | Date start, Date end) { | ||||
java.util.Calendar calendar = event.getComponent() | java.util.Calendar calendar = event.getComponent() | ||||
.getInternalCalendar(); | .getInternalCalendar(); | ||||
if (isThisMonth(calendar, start) | |||||
if (isThisMonth(calendar, start) | |||||
&& isThisMonth(calendar, end)) { | && isThisMonth(calendar, end)) { | ||||
super.setDates(event, start, end); | super.setDates(event, start, end); | ||||
} | } | ||||
javaCalendar = event.getComponent().getInternalCalendar(); | javaCalendar = event.getComponent().getInternalCalendar(); | ||||
super.eventMove(event); | super.eventMove(event); | ||||
} | } | ||||
protected void setDates(CalendarEventEditor event, | protected void setDates(CalendarEventEditor event, | ||||
Date start, Date end) { | Date start, Date end) { | ||||
if (isThisMonth(javaCalendar, start) | if (isThisMonth(javaCalendar, start) | ||||
events.add(BasicEvent); | events.add(BasicEvent); | ||||
} | } | ||||
public List<CalendarEvent> getEvents(Date startDate, | |||||
public List<CalendarEvent> getEvents(Date startDate, | |||||
Date endDate) { | Date endDate) { | ||||
return events; | return events; | ||||
} | } | ||||
final Window w = new Window(null, layout); | final Window w = new Window(null, layout); | ||||
... | ... | ||||
// Wrap the calendar event to a BeanItem | |||||
// Wrap the calendar event to a BeanItem | |||||
// and pass it to the form | // and pass it to the form | ||||
final BeanItem<CalendarEvent> item = | |||||
final BeanItem<CalendarEvent> item = | |||||
new BeanItem<CalendarEvent>(myEvent); | new BeanItem<CalendarEvent>(myEvent); | ||||
final Form form = new Form(); | final Form form = new Form(); | ||||
cal.setHandler(new BasicEventResizeHandler() { | cal.setHandler(new BasicEventResizeHandler() { | ||||
private static final long twelveHoursInMs = 12*60*60*1000; | private static final long twelveHoursInMs = 12*60*60*1000; | ||||
protected void setDates(CalendarEventEditor event, | |||||
protected void setDates(CalendarEventEditor event, | |||||
Date start, Date end) { | Date start, Date end) { | ||||
long eventLength = end.getTime() - start.getTime(); | long eventLength = end.getTime() - start.getTime(); | ||||
if (eventLength <= twelveHoursInMs) { | if (eventLength <= twelveHoursInMs) { | ||||
---- | ---- | ||||
endif::web[] | endif::web[] | ||||
Button enabled = new Button("Enabled"); | Button enabled = new Button("Enabled"); | ||||
enabled.setEnabled(true); // The default | enabled.setEnabled(true); // The default | ||||
layout.addComponent(enabled); | layout.addComponent(enabled); | ||||
Button disabled = new Button("Disabled"); | Button disabled = new Button("Disabled"); | ||||
disabled.setEnabled(false); | disabled.setEnabled(false); | ||||
layout.addComponent(disabled); | layout.addComponent(disabled); | ||||
TextField name = new TextField("Name"); | TextField name = new TextField("Name"); | ||||
name.setIcon(new ThemeResource("icons/user.png")); | name.setIcon(new ThemeResource("icons/user.png")); | ||||
layout.addComponent(name); | layout.addComponent(name); | ||||
// Component with an icon from another theme ('runo') | // Component with an icon from another theme ('runo') | ||||
Button ok = new Button("OK"); | Button ok = new Button("OK"); | ||||
ok.setIcon(new ThemeResource("../runo/icons/16/ok.png")); | ok.setIcon(new ThemeResource("../runo/icons/16/ok.png")); | ||||
---- | ---- | ||||
// Component for which the locale is meaningful | // Component for which the locale is meaningful | ||||
InlineDateField date = new InlineDateField("Datum"); | InlineDateField date = new InlineDateField("Datum"); | ||||
// German language specified with ISO 639-1 language | // German language specified with ISO 639-1 language | ||||
// code and ISO 3166-1 alpha-2 country code. | |||||
// code and ISO 3166-1 alpha-2 country code. | |||||
date.setLocale(new Locale("de", "DE")); | date.setLocale(new Locale("de", "DE")); | ||||
date.setResolution(Resolution.DAY); | date.setResolution(Resolution.DAY); | ||||
layout.addComponent(date); | layout.addComponent(date); | ||||
---- | ---- | ||||
ResourceBundle bundle = | ResourceBundle bundle = | ||||
ResourceBundle.getBundle(MyAppCaptions.class.getName(), | ResourceBundle.getBundle(MyAppCaptions.class.getName(), | ||||
UI.getCurrent().getLocale()); | UI.getCurrent().getLocale()); | ||||
// Get a localized resource from the bundle | // Get a localized resource from the bundle | ||||
Button cancel = | Button cancel = | ||||
new Button(bundle.getString(MyAppCaptions.CancelKey)); | new Button(bundle.getString(MyAppCaptions.CancelKey)); | ||||
// The locale in which we want to have the language | // The locale in which we want to have the language | ||||
// selection list | // selection list | ||||
Locale displayLocale = Locale.ENGLISH; | Locale displayLocale = Locale.ENGLISH; | ||||
// All known locales | // All known locales | ||||
final Locale[] locales = Locale.getAvailableLocales(); | final Locale[] locales = Locale.getAvailableLocales(); | ||||
// Allow selecting a language. We are in a constructor of a | // Allow selecting a language. We are in a constructor of a | ||||
// CustomComponent, so preselecting the current | // CustomComponent, so preselecting the current | ||||
// language of the application can not be done before | // language of the application can not be done before | ||||
select.addItem(locales[i]); | select.addItem(locales[i]); | ||||
select.setItemCaption(locales[i], | select.setItemCaption(locales[i], | ||||
locales[i].getDisplayName(displayLocale)); | locales[i].getDisplayName(displayLocale)); | ||||
// Automatically select the current locale | // Automatically select the current locale | ||||
if (locales[i].equals(getLocale())) | if (locales[i].equals(getLocale())) | ||||
select.setValue(locales[i]); | select.setValue(locales[i]); | ||||
new InlineDateField("Calendar in the selected language"); | new InlineDateField("Calendar in the selected language"); | ||||
date.setResolution(Resolution.DAY); | date.setResolution(Resolution.DAY); | ||||
layout.addComponent(date); | layout.addComponent(date); | ||||
// Handle language selection | // Handle language selection | ||||
select.addValueChangeListener(new Property.ValueChangeListener() { | select.addValueChangeListener(new Property.ValueChangeListener() { | ||||
public void valueChange(ValueChangeEvent event) { | public void valueChange(ValueChangeEvent event) { | ||||
readwrite.setValue("You can change this"); | readwrite.setValue("You can change this"); | ||||
readwrite.setReadOnly(false); // The default | readwrite.setReadOnly(false); // The default | ||||
layout.addComponent(readwrite); | layout.addComponent(readwrite); | ||||
TextField readonly = new TextField("Read-Only"); | TextField readonly = new TextField("Read-Only"); | ||||
readonly.setValue("You can't touch this!"); | readonly.setValue("You can't touch this!"); | ||||
readonly.setReadOnly(true); | readonly.setReadOnly(true); | ||||
and some of such changes could be acceptable, such as change in the scroll bar | and some of such changes could be acceptable, such as change in the scroll bar | ||||
position of a [classname]#Table#. Custom widgets should check the read-only | position of a [classname]#Table#. Custom widgets should check the read-only | ||||
state for variables bound to business | state for variables bound to business | ||||
data.//// | |||||
TODO: Note this also in the Advanced: Security section and possibly also in the | |||||
GWT | |||||
chapter. | |||||
data. | |||||
//// | |||||
TODO: Note this also in the Advanced: Security section. | |||||
Possibly also in the GWT chapter. | |||||
//// | //// | ||||
=== CSS Style Rules | === CSS Style Rules | ||||
background: lightblue; | background: lightblue; | ||||
} | } | ||||
---- | ---- | ||||
Setting the component also in immediate mode may be necessary, as otherwise the | Setting the component also in immediate mode may be necessary, as otherwise the | ||||
item would not be added immediately when the user interacts with the component, | item would not be added immediately when the user interacts with the component, | ||||
but after some other component causes a server | but after some other component causes a server | ||||
request.//// | |||||
TODO This could be a | |||||
bug | |||||
//// | |||||
request. | |||||
// TODO This could be a bug | |||||
[source, java] | [source, java] |
== Index |
((("JPAContainer", id="term.jpacontainer", range="startofrange"))) | ((("JPAContainer", id="term.jpacontainer", range="startofrange"))) | ||||
This chapter describes the use of the Vaadin JPAContainer add-on. | This chapter describes the use of the Vaadin JPAContainer add-on. | ||||
include::jpacontainer-overview.asciidoc[leveloffset=+2] | include::jpacontainer-overview.asciidoc[leveloffset=+2] | ||||
include::jpacontainer-installation.asciidoc[leveloffset=+2] | include::jpacontainer-installation.asciidoc[leveloffset=+2] |
|=============== | |=============== | ||||
The field factory is recusive, so that you can edit a complex object tree with | |||||
one form. | |||||
The field factory is recursive, so that you can edit a complex object tree with one form. | |||||
[[jpacontainer.fieldfactory.configuring]] | [[jpacontainer.fieldfactory.configuring]] | ||||
== Configuring the Field Factory | == Configuring the Field Factory | ||||
The [classname]#FieldFactory# is highly configurable with various configuration | |||||
settings and by | |||||
extending.//// | |||||
You need to make the configuration | |||||
before | |||||
//// | |||||
The [classname]#FieldFactory# is highly configurable with various configuration settings and by extending. | |||||
// You need to make the configuration before ... | |||||
The [methodname]#setMultiSelectType()# and [methodname]#setSingleSelectType()# | The [methodname]#setMultiSelectType()# and [methodname]#setSingleSelectType()# | ||||
allow you to specify a selection component that is used instead of the default | allow you to specify a selection component that is used instead of the default | ||||
// Get the item to edit in the form | // Get the item to edit in the form | ||||
Item countryItem = | Item countryItem = | ||||
countries.getItem(event.getProperty().getValue()); | countries.getItem(event.getProperty().getValue()); | ||||
// Use a JPAContainer field factory | // Use a JPAContainer field factory | ||||
// - no configuration is needed here | // - no configuration is needed here | ||||
final FieldFactory fieldFactory = new FieldFactory(); | final FieldFactory fieldFactory = new FieldFactory(); | ||||
// Edit the item in the form | // Edit the item in the form | ||||
countryForm.setItemDataSource(countryItem); | countryForm.setItemDataSource(countryItem); | ||||
countryForm.setEnabled(true); | countryForm.setEnabled(true); | ||||
// Handle saves on the form | // Handle saves on the form | ||||
final Button save = new Button("Save"); | final Button save = new Button("Save"); | ||||
countryForm.getFooter().removeAllComponents(); | countryForm.getFooter().removeAllComponents(); | ||||
<<figure.jpacontainer.fieldfactory.using>>, the factory creates a | <<figure.jpacontainer.fieldfactory.using>>, the factory creates a | ||||
[classname]#MasterDetailEditor# for all properties with a | [classname]#MasterDetailEditor# for all properties with a | ||||
[literal]#++@OneToMany++# or an [literal]#++@ElementCollection++# annotation. | [literal]#++@OneToMany++# or an [literal]#++@ElementCollection++# annotation. | ||||
[[layout]] | [[layout]] | ||||
== Managing Layout | == Managing Layout | ||||
//// | |||||
TODO The intro text below is now completely hidden, as this text is | |||||
not visible in web edition and all the text is web-conditional. | |||||
//// | |||||
ifdef::web[] | ifdef::web[] | ||||
Ever since the ancient xeroxians invented graphical user interfaces, programmers | Ever since the ancient xeroxians invented graphical user interfaces, programmers | ||||
have wanted to make GUI programming ever easier for themselves. Solutions | have wanted to make GUI programming ever easier for themselves. Solutions | ||||
need to have more control. They need to be able to change the state of user | need to have more control. They need to be able to change the state of user | ||||
interface components and even their layout on the run. This creates a need to | interface components and even their layout on the run. This creates a need to | ||||
separate the presentation from content on exactly the right | separate the presentation from content on exactly the right | ||||
level.//// | |||||
level. | |||||
//// | |||||
Vaadin provides a solution for this, using themes and CSS, but let us first look | Vaadin provides a solution for this, using themes and CSS, but let us first look | ||||
at what Java did for UI | |||||
programming. | |||||
at what Java did for UI programming. | |||||
//// | //// | ||||
//// | //// | ||||
Changing the layout steps right on the feet of the graphics designers, so we | Changing the layout steps right on the feet of the graphics designers, so we | ||||
have a conflict. We will discuss this conflict later, but let us first look at | have a conflict. We will discuss this conflict later, but let us first look at | ||||
what Java did for UI | |||||
programming. | |||||
what Java did for UI programming. | |||||
//// | //// | ||||
endif::web[] | endif::web[] | ||||
[source, java] | [source, java] | ||||
---- | ---- | ||||
CssLayout layout = new CssLayout(); | CssLayout layout = new CssLayout(); | ||||
// Component with a layout-managed caption and icon | // Component with a layout-managed caption and icon | ||||
TextField tf = new TextField("A TextField"); | TextField tf = new TextField("A TextField"); | ||||
tf.setIcon(new ThemeResource("icons/user.png")); | tf.setIcon(new ThemeResource("icons/user.png")); | ||||
Label label = new Label("A Label"); | Label label = new Label("A Label"); | ||||
label.setWidth(Sizeable.SIZE_UNDEFINED, 0); | label.setWidth(Sizeable.SIZE_UNDEFINED, 0); | ||||
layout.addComponent(label); | layout.addComponent(label); | ||||
layout.addComponent(new Button("A Button")); | layout.addComponent(new Button("A Button")); | ||||
---- | ---- | ||||
and to handle the differences in different browsers. Some browsers, no need to | and to handle the differences in different browsers. Some browsers, no need to | ||||
say which, are notoriously incompatible with the CSS standards, so they require | say which, are notoriously incompatible with the CSS standards, so they require | ||||
a lot of custom CSS. You may need to make use of the browser-specific style | a lot of custom CSS. You may need to make use of the browser-specific style | ||||
classes in the root element of the | |||||
application.//// | |||||
TODO: described in <xref | |||||
linkend="advanced.browserinfo"/> | |||||
//// | |||||
classes in the root element of the application. | |||||
// TODO: ... described in <<advanced.browserinfo>> | |||||
Some features in the other layouts are not even solvable in pure CSS, at least | Some features in the other layouts are not even solvable in pure CSS, at least | ||||
in all browsers. | in all browsers. | ||||
[[layout.csslayout.css]] | [[layout.csslayout.css]] | ||||
== Styling with CSS | == Styling with CSS | ||||
[source, css] | [source, css] | ||||
---- | ---- | ||||
.v-csslayout {} | .v-csslayout {} | ||||
For example, we could style the basic [classname]#CssLayout# example shown | For example, we could style the basic [classname]#CssLayout# example shown | ||||
earlier as follows: | earlier as follows: | ||||
[source, css] | [source, css] | ||||
---- | ---- | ||||
/* Have the caption right of the text box, bottom-aligned */ | /* Have the caption right of the text box, bottom-aligned */ | ||||
wrapping in [literal]#++inline-block++# mode, as wrapping can occur between the | wrapping in [literal]#++inline-block++# mode, as wrapping can occur between the | ||||
caption and its corresponding component element just as well as between | caption and its corresponding component element just as well as between | ||||
components. Such use case is therefore not feasible. | components. Such use case is therefore not feasible. | ||||
[options="compact"] | [options="compact"] | ||||
* Application packaged as a WAR | * Application packaged as a WAR | ||||
[options="compact"] | |||||
** [filename]#WEB-INF/portlet.xml# descriptor | ** [filename]#WEB-INF/portlet.xml# descriptor | ||||
** [filename]#WEB-INF/liferay-portlet.xml# descriptor for Liferay | ** [filename]#WEB-INF/liferay-portlet.xml# descriptor for Liferay | ||||
** [filename]#WEB-INF/liferay-plugin-package.properties# for Liferay | ** [filename]#WEB-INF/liferay-plugin-package.properties# for Liferay | ||||
* Widget set installed to portal (optional) | * Widget set installed to portal (optional) | ||||
* Themes installed to portal (optional) | * Themes installed to portal (optional) | ||||
* Vaadin libraries installed to portal (optional) | * Vaadin libraries installed to portal (optional) | ||||
* Portal configuration settings (optional) | * Portal configuration settings (optional) | ||||
The Vaadin Plugin for Eclipse creates these files for you, when you create a | The Vaadin Plugin for Eclipse creates these files for you, when you create a | ||||
portlet project as described in | |||||
<<dummy/../../../framework/portal/portal-eclipse#portal.eclipse,"Creating a | |||||
Generic Portlet in Eclipse">>. | |||||
Installing the widget set and themes to the portal is required for running two | |||||
or more Vaadin portlets simultaneously in a single portal page. As this | |||||
situation occurs quite easily, we recommend installing them in any case. | |||||
Instructions for Liferay are given in | |||||
<<dummy/../../../framework/portal/portal-liferay#portal.liferay,"Developing | |||||
Vaadin Portlets for Liferay">> and the procedure is similar for other portals. | |||||
portlet project as described in <<portal-eclipse#portal.eclipse,"Creating a Generic Portlet in Eclipse">>. | |||||
Installing the widget set and themes to the portal is required for running two or more Vaadin portlets simultaneously in a single portal page. | |||||
As this situation occurs quite easily, we recommend installing them in any case. | |||||
Instructions for Liferay are given in <<portal-liferay#portal.liferay,"Developing Vaadin Portlets for Liferay">> and the procedure is similar for other portals. | |||||
In addition to the Vaadin libraries, you will need to have the | In addition to the Vaadin libraries, you will need to have the | ||||
[filename]#portlet.jar# in your project classpath. However, notice that you must | [filename]#portlet.jar# in your project classpath. However, notice that you must | ||||
[[portal.deployment.descriptor]] | [[portal.deployment.descriptor]] | ||||
== Portlet Deployment Descriptor | == Portlet Deployment Descriptor | ||||
The portlet WAR must include a portlet descriptor located at | |||||
[filename]#WEB-INF/portlet.xml#. A portlet definition includes the portlet name, | |||||
mapping to a servlet, modes supported by the portlet, and other configuration. | |||||
Below is an example of a simple portlet definition in [filename]#portlet.xml# | |||||
descriptor. | |||||
The portlet WAR must include a portlet descriptor located at [filename]#WEB-INF/portlet.xml#. | |||||
A portlet definition includes the portlet name, mapping to a servlet, modes supported by the portlet, and other configuration. | |||||
Below is an example of a simple portlet definition in [filename]#portlet.xml# descriptor. | |||||
[subs="normal"] | |||||
[subs="verbatim,replacements,quotes"] | |||||
---- | ---- | ||||
<?xml version="1.0" encoding="UTF-8" standalone="no"?> | <?xml version="1.0" encoding="UTF-8" standalone="no"?> | ||||
<portlet-app | <portlet-app | ||||
http://java.sun.com/xml/ns/portlet/portlet-app_2_0.xsd"> | http://java.sun.com/xml/ns/portlet/portlet-app_2_0.xsd"> | ||||
<portlet> | <portlet> | ||||
<portlet-name>**Portlet Example portlet**</portlet-name> | |||||
<display-name>**Vaadin Portlet Example**</display-name> | |||||
<portlet-name>[replaceable]##Portlet Example portlet##</portlet-name> | |||||
<display-name>[replaceable]##Vaadin Portlet Example##</display-name> | |||||
<!-- Map portlet to a servlet. --> | <!-- Map portlet to a servlet. --> | ||||
<portlet-class> | <portlet-class> | ||||
<name>UI</name> | <name>UI</name> | ||||
<!-- The application class with package name. --> | <!-- The application class with package name. --> | ||||
<value>**com.example.myportlet.MyportletUI**</value> | |||||
<value>[replaceable]##com.example.myportlet.MyportletUI##</value> | |||||
</init-param> | </init-param> | ||||
<!-- Supported portlet modes and content types. --> | <!-- Supported portlet modes and content types. --> | ||||
<!-- Not always required but Liferay requires these. --> | <!-- Not always required but Liferay requires these. --> | ||||
<portlet-info> | <portlet-info> | ||||
<title>**Vaadin Portlet Example**</title> | |||||
<short-title>**Portlet Example**</short-title> | |||||
<title>[replaceable]##Vaadin Portlet Example##</title> | |||||
<short-title>[replaceable]##Portlet Example##</short-title> | |||||
</portlet-info> | </portlet-info> | ||||
</portlet> | </portlet> | ||||
</portlet-app> | </portlet-app> | ||||
---- | ---- | ||||
Listing supported portlet modes in [filename]#portlet.xml# enables the | |||||
corresponding portlet controls in the portal user interface that allow changing | |||||
the mode, as described later. | |||||
The mode definitions enable the corresponding portlet controls in the portal. | |||||
The portlet controls allow changing the mode of the portlet, as described later. | |||||
[[portal.deployment.liferay]] | [[portal.deployment.liferay]] | ||||
== Liferay Portlet Descriptor | == Liferay Portlet Descriptor | ||||
((("Liferay", "portlet descriptor", id="term.portal.liferay.descriptor.liferay-portlet.liferay", range="startofrange"))) | ((("Liferay", "portlet descriptor", id="term.portal.liferay.descriptor.liferay-portlet.liferay", range="startofrange"))) | ||||
Liferay requires a special [filename]#liferay-portlet.xml# descriptor file that | Liferay requires a special [filename]#liferay-portlet.xml# descriptor file that | ||||
defines Liferay-specific parameters. Especially, Vaadin portlets must be defined | defines Liferay-specific parameters. Especially, Vaadin portlets must be defined | ||||
as " __instanceable__", but not " __ajaxable__". | as " __instanceable__", but not " __ajaxable__". | ||||
<portlet> | <portlet> | ||||
<!-- Matches definition in portlet.xml. --> | <!-- Matches definition in portlet.xml. --> | ||||
<!-- Note: Must not be the same as servlet name. --> | <!-- Note: Must not be the same as servlet name. --> | ||||
<portlet-name>**Portlet Example portlet**</portlet-name> | |||||
<portlet-name>[replaceable]##Portlet Example portlet##</portlet-name> | |||||
<instanceable>true</instanceable> | <instanceable>true</instanceable> | ||||
<ajaxable>false</ajaxable> | <ajaxable>false</ajaxable> | ||||
[[figure.portal.liferay.descriptor.display]] | [[figure.portal.liferay.descriptor.display]] | ||||
.Portlet Categories in Add Application Window | .Portlet Categories in Add Application Window | ||||
image::img/liferay-display-hi.png[] | |||||
image::img/liferay-display-hi.png[width=60%] | |||||
See Liferay documentation for further details on how to configure the categories | See Liferay documentation for further details on how to configure the categories | ||||
in the [filename]#liferay-display.xml# deployment descriptor. | in the [filename]#liferay-display.xml# deployment descriptor. | ||||
[subs="normal"] | [subs="normal"] | ||||
---- | ---- | ||||
name=**Portlet Example portlet** | |||||
short-description=**myportlet** | |||||
module-group-id=**Vaadin** | |||||
name=[replaceable]##Portlet Example portlet## | |||||
short-description=[replaceable]##myportlet## | |||||
module-group-id=[replaceable]##Vaadin## | |||||
module-incremental-version=1 | module-incremental-version=1 | ||||
#change-log= | #change-log= | ||||
#page-uri= | #page-uri= | ||||
#author= | #author= | ||||
license=Proprietary | license=Proprietary | ||||
portal-dependency-jars=\ | portal-dependency-jars=\ | ||||
**vaadin.jar** | |||||
[replaceable]##vaadin.jar## | |||||
---- | ---- | ||||
[parameter]#name#:: The plugin name must match the portlet name. | [parameter]#name#:: The plugin name must match the portlet name. | ||||
which Liferay runs; for example, if you use Liferay bundled with Tomcat, you | which Liferay runs; for example, if you use Liferay bundled with Tomcat, you | ||||
will find the extracted package in the [filename]#webapps# directory under the | will find the extracted package in the [filename]#webapps# directory under the | ||||
Tomcat installation directory included in Liferay. | Tomcat installation directory included in Liferay. | ||||
Custom themes are placed in the [filename]#VAADIN/themes# folder of the web | Custom themes are placed in the [filename]#VAADIN/themes# folder of the web | ||||
application, in an Eclipse project under the [filename]#WebContent# folder or | application, in an Eclipse project under the [filename]#WebContent# folder or | ||||
[filename]#src/main/webapp# in Maven projects, as was illustrated in | [filename]#src/main/webapp# in Maven projects, as was illustrated in | ||||
<<dummy/../../../framework/themes/themes-overview#figure.themes.theme-contents,"Contents | |||||
of a Theme">>. This location is fixed. You need to have a theme folder for each | |||||
<<themes-overview#figure.themes.theme-contents,"Contents of a Theme">>. This location is fixed. You need to have a theme folder for each | |||||
theme you use in your application, although applications rarely need more than a | theme you use in your application, although applications rarely need more than a | ||||
single theme. | single theme. | ||||
You can use Sass themes in Vaadin in two ways, either by compiling them to CSS | You can use Sass themes in Vaadin in two ways, either by compiling them to CSS | ||||
by yourself or by letting the Vaadin servlet compile them for you on-the-fly | by yourself or by letting the Vaadin servlet compile them for you on-the-fly | ||||
when the theme CSS is requested by the browser, as described in | when the theme CSS is requested by the browser, as described in | ||||
<<dummy/../../../framework/themes/themes-compiling#themes.compiling,"Compiling | |||||
Sass Themes">>. | |||||
<<themes-compiling#themes.compiling,"Compiling Sass Themes">>. | |||||
To define a Sass theme with the name mytheme, you must place a file with name | To define a Sass theme with the name mytheme, you must place a file with name | ||||
[filename]#styles.scss# in the theme folder [filename]#VAADIN/themes/mytheme#. | [filename]#styles.scss# in the theme folder [filename]#VAADIN/themes/mytheme#. | ||||
component. | component. | ||||
Please see the section on each component for a description of its styles. Most | Please see the section on each component for a description of its styles. Most | ||||
of the stylenames are determined in the client-side widget of each component. | |||||
of the style names are determined in the client-side widget of each component. | |||||
The easiest way to find out the styles of the elements is to use a HTML | The easiest way to find out the styles of the elements is to use a HTML | ||||
inspector such as | |||||
FireBug.//// | |||||
TODO reference to a Firebug section when | |||||
available | |||||
//// | |||||
inspector such as FireBug. | |||||
//TODO add reference to a Firebug section when available | |||||
Some client-side components or component styles can be shared by different | Some client-side components or component styles can be shared by different | ||||
server-side components. For example, [literal]#++v-textfield++# style is used | server-side components. For example, [literal]#++v-textfield++# style is used | ||||
public class MyUI extends UI { | public class MyUI extends UI { | ||||
@Override | @Override | ||||
protected void init(VaadinRequest request) { | protected void init(VaadinRequest request) { | ||||
... | |||||
... | |||||
Panel panel = new Panel("Regular Panel in the Runo Theme"); | Panel panel = new Panel("Regular Panel in the Runo Theme"); | ||||
panel.addComponent(new Button("Regular Runo Button")); | panel.addComponent(new Button("Regular Runo Button")); | ||||
// A button with the "small" style | // A button with the "small" style | ||||
Button smallButton = new Button("Small Runo Button"); | Button smallButton = new Button("Small Runo Button"); | ||||
smallButton.addStyleName(Runo.BUTTON_SMALL); | smallButton.addStyleName(Runo.BUTTON_SMALL); | ||||
The add-on themes need to be included in the project theme. Vaadin Plugin for | The add-on themes need to be included in the project theme. Vaadin Plugin for | ||||
Eclipse and Maven automatically include them in the [filename]#addons.scss# file | Eclipse and Maven automatically include them in the [filename]#addons.scss# file | ||||
in the project theme folder. It should be included by the project theme. | in the project theme folder. It should be included by the project theme. | ||||
((("CSS", "introduction", id="term.themes.css", range="startofrange"))) | ((("CSS", "introduction", id="term.themes.css", range="startofrange"))) | ||||
Cascading Style Sheets or CSS is the basic technique to separate the appearance | Cascading Style Sheets or CSS is the basic technique to separate the appearance | ||||
of a web page from the content represented in HTML. In this section, we give an | of a web page from the content represented in HTML. In this section, we give an | ||||
introduction to CSS and look how they are relevant to software development with | introduction to CSS and look how they are relevant to software development with | ||||
The HTML elements that will be styled later by matching CSS rules are emphasized | The HTML elements that will be styled later by matching CSS rules are emphasized | ||||
above. | above. | ||||
The [literal]#++<link>++# element in the HTML header defines the used CSS | |||||
stylesheet. The definition is automatically generated by Vaadin in the HTML page | |||||
The [elementname]#link# element in the HTML header defines the CSS stylesheet. | |||||
The definition is automatically generated by Vaadin in the HTML page | |||||
that loads the UI of the application. A stylesheet can also be embedded in the | that loads the UI of the application. A stylesheet can also be embedded in the | ||||
HTML document itself, as is done when optimizing their loading in Vaadin | HTML document itself, as is done when optimizing their loading in Vaadin | ||||
TouchKit, for example. | TouchKit, for example. | ||||
Let us look at an example that matches certain elements in the simple HTML | Let us look at an example that matches certain elements in the simple HTML | ||||
document given in the previous section: | document given in the previous section: | ||||
[source, css] | [source, css] | ||||
---- | ---- | ||||
p, td { | |||||
p, td { | |||||
color: blue; | color: blue; | ||||
} | } | ||||
td { | |||||
td { | |||||
background: yellow; | background: yellow; | ||||
font-weight: bold; | font-weight: bold; | ||||
} | } | ||||
---- | ---- | ||||
The [literal]#++p++# and [literal]#++td++# are element type selectors that match | The [literal]#++p++# and [literal]#++td++# are element type selectors that match | ||||
with [literal]#++<p>++# and [literal]#++<td>++# elements in HTML, respectively. | |||||
with [elementname]#p# and [elementname]#td# elements in HTML, respectively. | |||||
The first rule matches with both elements, while the second matches only with | The first rule matches with both elements, while the second matches only with | ||||
[literal]#++<td>++# elements. Let us assume that you have saved the above style | |||||
sheet with the name [filename]#mystylesheet.css# and consider the following HTML | |||||
file located in the same folder. | |||||
[elementname]#td# elements. | |||||
Let us assume that you have saved the above style sheet with the name [filename]#mystylesheet.css# and consider the following HTML file located in the same folder. | |||||
[[figure.themes.basic.1]] | [[figure.themes.basic.1]] | ||||
.Simple Styling by Element Type | .Simple Styling by Element Type | ||||
parent elements. For example, let us change the above example and define it | parent elements. For example, let us change the above example and define it | ||||
instead as follows: | instead as follows: | ||||
[source, css] | [source, css] | ||||
---- | ---- | ||||
table { | table { | ||||
} | } | ||||
---- | ---- | ||||
All elements contained in the [literal]#++<table>++# element would have the same | |||||
properties. For example, the text in the contained [literal]#++<td>++# elements | |||||
would be in blue color. | |||||
All elements contained in the [elementname]#table# element would have the same properties. | |||||
For example, the text in the contained [elementname]#td# elements would be in blue color. | |||||
[[themes.css.basics.element-types]] | [[themes.css.basics.element-types]] | ||||
=== HTML Element Types | === HTML Element Types | ||||
HTML has a number of element types, each of which accepts a specific set of | HTML has a number of element types, each of which accepts a specific set of | ||||
properties. The [literal]#++<div>++# elements are generic elements that can be | |||||
properties. The [elementname]#div# elements are generic elements that can be | |||||
used to create almost any layout and formatting that can be created with a | used to create almost any layout and formatting that can be created with a | ||||
specific HTML element type. Vaadin uses [literal]#++<div>++# elements | |||||
specific HTML element type. Vaadin uses [elementname]#div# elements | |||||
extensively to draw the UI, especially in layout components. | extensively to draw the UI, especially in layout components. | ||||
((("Google Web Toolkit", | |||||
"themeing"))) | |||||
((("Google Web Toolkit", "themeing"))) | |||||
Matching elements by their type as shown above is, however, rarely if ever used | Matching elements by their type as shown above is, however, rarely if ever used | ||||
in style sheets for Vaadin applications. We used it above, because it is the | in style sheets for Vaadin applications. We used it above, because it is the | ||||
normal way in regular HTML documents that use the various HTML elements for | normal way in regular HTML documents that use the various HTML elements for | ||||
formatting text, but it is not applicable in Vaadin UIs that consist mostly of | formatting text, but it is not applicable in Vaadin UIs that consist mostly of | ||||
[literal]#++<div>++# elements. Instead, you need to match by element class, as | |||||
[elementname]#div# elements. Instead, you need to match by element class, as | |||||
described next. | described next. | ||||
</body> | </body> | ||||
</html> | </html> | ||||
---- | ---- | ||||
The class attributes of HTML elements can be matched in CSS rules with a | The class attributes of HTML elements can be matched in CSS rules with a | ||||
selector notation where the class name is written after a period following the | selector notation where the class name is written after a period following the | ||||
element name. This gives us full control of matching elements by their type and | element name. This gives us full control of matching elements by their type and | ||||
To ensure future compatibility, we recommend that you use only matching based on | To ensure future compatibility, we recommend that you use only matching based on | ||||
the classes and __do not__ match for specific HTML element types in CSS rules, | the classes and __do not__ match for specific HTML element types in CSS rules, | ||||
because Vaadin may change the exact HTML implementation how components are drawn | because Vaadin may change the exact HTML implementation how components are drawn | ||||
in the future. For example, Vaadin earlier used [literal]#++<div>++# element to | |||||
draw [classname]#Button# components, but later it was changed to use the | |||||
special-purpose [literal]#++<button>++# element in HTML. Because of using the | |||||
[literal]#++v-button++# style class in the CSS rules for the button, styling it | |||||
has changed only very little. | |||||
in the future. | |||||
For example, Vaadin earlier used [elementname]#div# element to draw [classname]#Button# components, but later it was changed to use the special-purpose [elementname]#button# element in HTML. | |||||
Because of using the [literal]#++v-button++# style class in the CSS rules for the button, styling it has changed only very little. | |||||
[[themes.css.matching-by-descendants]] | [[themes.css.matching-by-descendants]] | ||||
</table> | </table> | ||||
</body> | </body> | ||||
---- | ---- | ||||
Matching by the class name [literal]#++.mytext++# alone would match both the | |||||
[literal]#++<p>++# and [literal]#++<td>++# elements. If we want to match only | |||||
the table cell, we could use the following selector: | |||||
Matching by the class name [literal]#++.mytext++# alone would match both the [elementname]#p# and [elementname]#td# elements. | |||||
If we want to match only the table cell, we could use the following selector: | |||||
[source, css] | [source, css] | ||||
---- | ---- | ||||
// Label has v-label style | // Label has v-label style | ||||
content.addComponent(new Label("Hello World!")); | content.addComponent(new Label("Hello World!")); | ||||
// Button has v-button style | // Button has v-button style | ||||
content.addComponent(new Button("Push Me!", | content.addComponent(new Button("Push Me!", | ||||
new Button.ClickListener() { | new Button.ClickListener() { | ||||
.v-ui { | .v-ui { | ||||
background: white; | background: white; | ||||
} | } | ||||
/* All labels have white text on black background */ | /* All labels have white text on black background */ | ||||
.v-label { | .v-label { | ||||
background: black; | background: black; | ||||
(((range="endofrange", startref="term.themes.css"))) | (((range="endofrange", startref="term.themes.css"))) | ||||