Using Binder with Polymer Templates
Note
|
Use Lit templates instead
Lit templates are recommended. Polymer templates are available in the next long term supported Vaadin version (LTS), but they are deprecated.
|
Binder
is a server-side construct and you can therefore not use it in a Polymer template. It is, however, possible to create a form using the PolymerTemplate
API and to connect the component to a Binder
. The process is similar to using binders with declared components.
In this section, we demonstrate how to create a fully-functional template-binder view.
Creating the Polymer Template Component
The first step is to create the JavaScript Polymer template and its mapped Java class.
Example: Creating the user-form
JavaScript Polymer template.
import {PolymerElement, html} from '@polymer/polymer/polymer-element.js';
import '@vaadin/vaadin-form-layout/vaadin-form-layout.js';
import '@vaadin/vaadin-text-field/vaadin-text-field.js';
import '@vaadin/vaadin-text-field/vaadin-text-area.js';
import '@vaadin/vaadin-checkbox/vaadin-checkbox.js';
import './form-buttons-bar.js'
class UserForm extends PolymerElement {
static get template() {
return html`
<style>
</style>
<vaadin-form-layout id="form">
<vaadin-text-field id="email" label="Email (login)" colspan="2"></vaadin-text-field>
<vaadin-text-field id="first-name" label="First Name"></vaadin-text-field>
<vaadin-text-field id="last-name" label="Last Name"></vaadin-text-field>
<vaadin-text-area id="comments" label="Comments"></vaadin-text-area>
</vaadin-form-layout>
<form-buttons-bar id="action-buttons"></form-buttons-bar>`;
}
static get is() {
return 'user-form';
}
}
customElements.define(UserForm.is, UserForm);
Example: Creating the mapped UserForm
Java template class.
@Tag("user-form")
@JsModule("./src/user-form.js")
public class UserForm extends PolymerTemplate < UserForm.FormComponentModel > {
@Id("email")
private TextField email;
@Id("first-name")
private TextField firstName;
@Id("last-name")
private TextField lastName;
@Id("comments")
private TextArea comment;
@Id("action-buttons")
private FormButtonsBar actionButtons;
Creating and Linking the Binder
Next, we create and link the binder.
We start by declaring the binder as a class variable in the UserForm
class.
Example: Declaring the binder in the UserForm
class.
private Binder<User> binder;
Next, we create the initBinder
method that initializes the binder and links it to the fields in the form.
Example: Creating the initBinder
method and linking it to the form fields.
private void initBinder() {
binder = new Binder<>();
// email
binder.forField(email).withValidator(
new EmailValidator("This doesn't look like a valid email address")
).bind(User::getEmail, User::setEmail);
// firstName
binder.forField(firstName).withValidator(firstName -> firstName.length() > 1,
"The first name must contains at least 2 characters").asRequired()
.bind(User::getFirstName, User::setFirstName);
// lastName
binder.forField(lastName).asRequired("Last name can't be empty")
.bind(User::getLastName, User::setLastName);
// comment
binder.forField(comment).bind(User::getComment, User::setComment);
}
See Binding Data to Forms for more.
We can now call the initBinder
method inside the constructor of the class.
Example: Calling initBinder
in the UserForm
class.
public UserForm() {
initBinder();
}
Declaring Methods to Get and Set User Objects
Now that the binding process is complete, we can declare methods to get and set user objects in the form.
Example: Declaring methods to set, remove and get User
beans in the UserForm
class.
/**
* Connects the bean to the binder.
*
* @param user bean
*/
public void setBean(User user) {
binder.setBean(user);
}
/**
* Clears the form and disconnnect any bean.
*/
public void removeBean() {
binder.removeBean();
}
/**
* Gets the binder of the UserForm
*
* @return binder it binds the fields of an object to the fields shown
*/
public Optional<User> getBean() {
return Optional.of(binder.getBean());
}
-
An unbuffered binding is used.
Note
|
|
See Loading From and Saving To Business Objects for more.
Using the UserForm Component
The UserForm
component is now ready for use in other parts of your code.
Creating the Main View
First, we create the MainView
Polymer template component. This component displays a grid of users and our new UserForm
component. For the grid, we use the Vaadin Grid
component
Here is the result.
Example: Creating the main-view
JavaScript Polymer template.
import {PolymerElement, html} from '@polymer/polymer/polymer-element.js';
import '@vaadin/vaadin-grid/vaadin-grid.js'
import './user-form.js';
class MainView extends PolymerElement {
static get template() {
return html`
<style>
</style>
<div id="main-container">
<vaadin-grid id="users-grid"></vaadin-grid>
<user-form id="user-form"></user-form>
</div>`;
}
static get is() {
return 'main-view';
}
}
customElements.define(MainView.is, MainView);
Example: Creating the mapped MainView
Java template class.
@Tag("main-view")
@JsModule("./src/main-view.js")
@Route("")
public class MainView extends PolymerTemplate<TemplateModel> {
@Id("user-form")
private UserForm userForm;
@Id("users-grid")
private UsersGrid usersGrid;
}
Initializing the MainView Component
Next, we configure the components and binder, and initialize their listeners in the MainView
class.
Example: Initializing the MainView
component and its component’s listeners.
/**
* Initializes the Main view and the listeners of its components.
*/
public MainView() {
// selection listener on the rows of the grid.
usersGrid.addSelectionListener(selectionEvent -> {
Optional<User> optionalUser = usersGrid.getSelectedItems().stream().findAny();
if (optionalUser.isPresent()) {
userForm.setBean(optionalUser.get());
setEditionEnabled(true);
} else {
userForm.removeBean();
setEditionEnabled(false);
}
});
initFormListeners();
}
Implementing Save, Cancel and Delete Listeners
The final step is to implement listeners for the Save, Cancel and Delete buttons in the initFormListener
.
Example: Implementing the save
listener in the MainView
class.
formButtonsBar.addSaveListener(saveEvent -> {
// it checks that all validators defined in the form pass without error.
if (!userForm.getBinder().validate().isOk()) {
return;
}
Optional<User> optionalUser = userForm.getBean();
if (optionalUser.isPresent()) {
User user = optionalUser.get();
user = UsersRepository.save(user);
usersGrid.refresh(user);
userForm.setBean(user); // update the data in the form
}
});
-
The code first checks the state of the bean.
-
If correct, it generates a user object from the
userForm
. -
The user is then saved calling a method of the repository.
-
The item in the grid is refreshed to show the changes.
Note
|
For buffered binding, you would need to call binder.writeBean() .
|
Note
|
|
Example: Implementing the cancel
listener in the MainView
class.
formButtonsBar.addCancelListener(cancelEvent -> {
usersGrid.deselectAll();
});
-
All the elements of the grid are deselected and the form is emptied.
-
Deselection of a row triggers an event that removes the bean. See the
usersGrid.addSelectionListener
implementation in the previous section.
Example: Implementing the delete
listener in the MainView
class.
formButtonsBar.addDeleteListener(deleteEvent -> {
Optional<User> optionalUser = usersGrid.getSelectedItems().stream().findAny();
if (optionalUser.isPresent()) {
UsersRepository.delete(optionalUser.get());
usersGrid.deselectAll();
usersGrid.refreshAll();
}
});
-
The user is selected from the grid, removed calling
UsersRepository.delete
, and the user (bean) is removed from theUserForm
. -
When a user (bean) is removed, the fields of the
UserForm
are cleared.