Add option to use PushState instead of URI fragments in Navigator (#10042)
* Navigator now by default uses pushState and normal URLs
* added documentation for pushState and updated Navigator documentation
* improving docs etc, adding one TODO to be solved before merging
* pushState/replaceState no work better with changing titles
* Making uri fragment navigator work when not using specially mapped UI
* Revert to older default, add annotation for selecting
* Fix tests, add null checks
* Reorder if-clause, fix tests
* Revert unnecessary test change
* Use correct variable in UI, fix test clean up
* Updates to JavaDocs, fix some methods and tests
* Add comments, fix test ui, TODO for fallbacks
* Navigation documentation, JavaDocs, removed TODOs
* Documentation fixes
* Improve JavaDocs
* Fix link name in documentation
* Improve throws declaration in getLocation
* Change documentation about the PushState based navigation
* Add since tags
* Add since tags for UI
6 år sedan |
123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372 |
- ---
- title: Designing UIs Declaratively
- order: 3
- layout: page
- ---
-
- [[application.declarative]]
- = Designing UIs Declaratively
-
- Declarative definition of composites and even entire UIs makes it easy for
- developers and especially graphical designers to work on visual designs without
- any coding. Designs can be modified even while the application is running, as
- can be the associated themes. A design is a representation of a component
- hierarcy, which can be accessed from Java code to implement dynamic UI logic, as
- well as data binding.
-
- For example, considering the following layout in Java:
-
-
- [source, java]
- ----
- VerticalLayout vertical = new VerticalLayout ();
- vertical.addComponent(new TextField("Name"));
- vertical.addComponent(new TextField("Street address"));
- vertical.addComponent(new TextField("Postal code"));
- layout.addComponent(vertical);
- ----
-
- You could define it declaratively with the following equivalent design:
-
- [source, html]
- ----
- <vaadin-vertical-layout>
- <vaadin-text-field caption="Name"/>
- <vaadin-text-field caption="Street address"/>
- <vaadin-text-field caption="Postal code"/>
- </vaadin-vertical-layout>
- ----
-
- Declarative designs can be crafted by hand, but are most conveniently created
- with the Vaadin Designer.
-
- In the following, we first go through the syntax of the declarative design
- files, and then see how to use them in applications by binding them to data and
- handling user interaction events.
-
- [[application.declarative.syntax]]
- == Declarative Syntax
-
- A design is an HTML document with custom elements for representing components
- and their configuration. A design has a single root component inside the HTML
- body element. Enclosing [literal]#++<html>++#, [literal]#++<head>++#, and
- [literal]#++<body>++# are optional, but necessary if you need to make namespace
- definitions for custom components. Other regular HTML elements may not be used
- in the file, except inside components that specifically accept HTML content.
-
- In a design, each nested element corresponds to a Vaadin component in a
- component tree. Components can have explicitly given IDs to enable binding them
- to variables in the Java code, as well as optional attributes.
-
- [source, html]
- ----
- <!DOCTYPE html>
- <html>
- <body>
- <vaadin-vertical-layout size-full>
- <!-- Label with HTML content -->
- <vaadin-label><b>Hello!</b> -
- How are you?</vaadin-label>
-
- <vaadin-grid _id="mygrid" caption="My Grid"
- size-full :expand/>
- </vaadin-vertical-layout>
- </body>
- </html>
- ----
-
- The DOCTYPE is not required, neither is the [literal]#++<html>++#, or
- [literal]#++<body>++# elements. Nevertheless, there may only be one design root
- element.
-
- The above design defines the same UI layout as done earlier with Java code, and
- illustrated in
- <<application-architecture#figure.application.architecture.example,"Simple
- Hierarchical UI">>.
-
-
- [[application.declarative.elements]]
- == Component Elements
-
- HTML elements of the declarative syntax are directly mapped to Vaadin components according to their Java class names.
- The tag of a component element has a namespace prefix separated by a dash.
- Vaadin core components, which are defined in the [package]#com.vaadin.ui# package, have [literal]#++vaadin-++# prefix.
- The rest of an element tag is determined from the Java class name of the component, by making it lower-case, while adding a dash (`-`) before every previously upper-case letter as a word separator.
- For example, [classname]#ComboBox# component has declarative element tag [vaadinelement]#vaadin-combo-box#.
-
- [[application.declarative.elements.prefix]]
- === Component Prefix to Package Mapping
-
- You can use any components in a design: components extending Vaadin components,
- composite components, and add-on components. To do so, you need to define a
- mapping from an element prefix to the Java package of the component. The prefix
- is used as a sort of a namespace.
-
- The mappings are defined in `<meta name="package-mapping" ...>`
- elements in the HTML head. A [parameter]#content# attribute defines a mapping,
- in notation with a prefix separated from the corresponding Java package name
- with a colon, such as `my:com.example.myapp`.
-
- For example, consider that you have the following composite class
- [classname]#com.example.myapp.ExampleComponent#:
-
- [source, java]
- ----
- package com.example.myapp;
-
- public class ExampleComponent extends CustomComponent {
- public ExampleComponent() {
- setCompositionRoot(new Label("I am an example."));
- }
- }
- ----
-
- You would make the package prefix mapping and then use the component as follows:
-
- [subs="normal"]
- ----
- <!DOCTYPE html>
- <html>
- <head>
- **<meta name="package-mapping"
- content="my:com.example.myapp" />**
- </head>
-
- <body>
- <vaadin-vertical-layout>
- <vaadin-label><b>Hello!</b> -
- How are you?</vaadin-label>
-
- <!-- Use it here -->
- **<my-example-component/>**
- </vaadin-vertical-layout>
- </body>
- </html>
- ----
-
- [[application.declarative.elements.inline]]
- === Inline Content and Data
-
- The element content can be used for certain default attributes, such as a button
- caption. For example:
-
-
- [source, html]
- ----
- <vaadin-button><b>OK</b></vaadin-button>
- ----
-
- Some components, such as selection components, allow defining inline data within
- the element. For example:
-
-
- [source, html]
- ----
- <vaadin-native-select>
- <option>Mercury</option>
- <option>Venus</option>
- <option selected>Earth</option>
- </vaadin-native-select>
- ----
-
- The declarative syntax of each component type is described in the JavaDoc API
- documentation of Vaadin.
-
-
-
- [[application.declarative.attributes]]
- == Component Attributes
-
- [[application.declarative.attributes.mapping]]
- === Attribute-to-Property Mapping
-
- Component properties are directly mapped to the attributes of the HTML elements
- according to the names of the properties. Attributes are written in lower-case
- letters and dash is used for word separation instead of upper-case letters in
- the Java methods, so that [literal]#++placeholder++# attribute is equivalent to
- [methodname]#setPlaceholder()#.
-
- For example, the __caption__ property, which you can set with
- [methodname]#setCaption()#, is represented as [literal]#++caption++# attribute.
- You can find the component properties by the setter methods in the
- link:https://vaadin.com/api/[JavaDoc API documentation] of the component
- classes.
-
-
- [source, html]
- ----
- <vaadin-text-field caption="Name" placeholder="Enter Name"/>
- ----
-
-
- [[application.declarative.attributes.parameters]]
- === Attribute Values
-
- Attribute parameters must be enclosed in quotes and the value given as a string
- must be convertible to the type of the property (string, integer, boolean, or
- enumeration). Object types are not supported.
-
- Some attribute names are given by a shorthand. For example,
- [parameter]#alternateText# property of the [classname]#Image# component, which
- you would set with [methodname]#setAlternateText()#, is given as the
- [literal]#++alt++# attribute.
-
- Boolean values must be either `true` or `false`.
- The value can be omitted, in which case `true` is assumed.
- For example, the [literal]#++enabled++# attribute is boolean and has default value "`true`", so `enabled="true"` and `enabled` and equivalent.
-
- [source, html]
- ----
- <vaadin-button enabled="false">OK</vaadin-button>
- ----
-
-
- [[application.declarative.attributes.parent]]
- === Parent Component Settings
-
- Certain settings, such as a component's alignment in a layout, are not done in
- the component itself, but in the layout. Attributes prefixed with colon (
- [literal]#++:++#) are passed to the containing component, with the component as
- a target parameter. For example, [literal]#++:expand="1"++# given for a
- component [parameter]#c# is equivalent to calling [methodname]#setExpandRatio(c,
- 1)# for the containing layout.
-
- [subs="normal"]
- ----
- <vaadin-vertical-layout size-full>
- <!-- Align right in the containing layout -->
- <vaadin-label width-auto **:right**>Hello!</vaadin-label>
-
- <!-- Expands to take up all remaining vertical space -->
- <vaadin-horizontal-layout size-full **:expand**>
- <!-- Automatic width - shrinks horizontally -->
- <vaadin-radio-button-group width-auto height-full/>
-
- <!-- Expands horizontally to take remaining space -->
- <vaadin-grid size-full **:expand**/>
- </vaadin-horizontal-layout>
- </vaadin-vertical-layout>
- ----
-
-
- [[application.declarative.identifiers]]
- == Component Identifiers
-
- Components can be identified by either an identifier or a caption. There are two
- types of identifiers: page-global and local. This allows accessing them from
- Java code and binding them to components, as described later in
- <<application.declarative.composite>>.
-
- The [literal]#++id++# attribute can be used to define a page-global identifier,
- which must be unique within the page. Another design or UI shown simultaneously
- in the same page may not have components sharing the same ID. Using global
- identifiers is therefore not recommended, except in special cases where
- uniqueness is ensured.
-
- The [literal]#++_id++# attribute defines a local identifier used only within the
- design. This is the recommended way to identifying components.
-
-
- [source, html]
- ----
- <vaadin-grid _id="mygrid" caption="My Grid"/>
- ----
-
-
- [[application.declarative.composite]]
- == Using Designs in Code
-
- The main use of declarative designs is in building application views, sub-views,
- dialogs, and forms through composition. The two main tasks are filling the
- designs with application data and handling user interaction events.
-
- [[application.declarative.composite.designroot]]
- === Binding to a Design Root
-
- You can bind any component container as the root component of a design with the
- [classname]#@DesignRoot# annotation. The class must match or extend the class of
- the root element in the design.
-
- The member variables are automatically initialized from the design according to
- the component identifiers (see <<application.declarative.identifiers>>), which
- must match the variable names.
-
- For example, the following class could be used to bind the design given earlier.
-
-
- [source, java]
- ----
- @DesignRoot
- public class MyViewDesign extends VerticalLayout {
- RadioButtonGroup<String> myRadioButtonGroup;
- Grid<String> myGrid;
-
- public MyViewDesign() {
- Design.read("MyDeclarativeUI.html", this);
-
- // Show some (example) data
- myCheckBoxGroup.setItems("Venus", "Earth", "Mars");
- myGrid.setItems(
- GridExample.generateContent());
-
- // Some interaction
- myCheckBoxGroup.addValueChangeListener(event ->
- Notification.show("Selected " +
- event.getValue());
- }
- }
- ----
-
- The design root class must match or extend the root element class of the design.
- For example, earlier we had [literal]#++<vaadin-vertical-layout>++# element in the
- HTML file, which can be bound to a class extending [classname]#VerticalLayout#.
-
-
- [[application.declarative.composite.using]]
- === Using a Design
-
- You can create and use a declaratively defined component just like any other component.
- For example, to use the previously defined design root component as the content
- of the entire UI:
-
-
- [source, java]
- ----
- public class DeclarativeViewUI extends UI {
- @Override
- protected void init(VaadinRequest request) {
- setContent(new MyViewDesign());
- }
- }
- ----
-
-
- [[application.declarative.composite.viewnavigation]]
- === Designs in View Navigation
-
- To use a design in view navigation, as described in
- <<../advanced/advanced-navigator#advanced.navigator,"Navigating
- in an Application">>, you just need to implement the [interfacename]#View#
- interface.
-
-
- [source, java]
- ----
- @DesignRoot
- public class MainView extends VerticalLayout
- implements View {
- public MainView() {
- Design.read(this);
- ...
- }
- ...
- }
-
- ...
- // Use the view by precreating it
- navigator.addView(MAINVIEW, new MainView());
- ----
-
- See
- <<../advanced/advanced-navigator#advanced.navigator.pathparam,"Handling
- Path Parameters">> for a complete example.
|