Binding Model Data
Warning
|
Polymer support has been deprecated since Vaadin 18 (released in November 2020), in favor of faster and simpler Lit templates. The built-in support for Polymer templates has been removed and is only available as a commercial add-on. However, a free conversion tool is available to assist in converting Polymer templates to Lit. Read more about setting up the commercial Polymer templates addon in the Upgrade Guide. |
Template model and model data aren’t supported for Lit templates. You may use directly, though, component API and properties via the Element
API to achieve the same functionality.
The way in which model values are bound to different parts of the element tree — defined by the template — is at the core of the PolymerTemplate
API.
The following three sections show how to bind text content, property values, and attribute values. The JavaScript template examples in these sections all use the following Java template and model class.
The example here is a PolymerBindingTemplate
template class:
@Tag("my-template")
@JsModule("./com/example/my-template.js")
public class PolymerBindingTemplate extends PolymerTemplate<BindingModel> {
public PolymerBindingTemplate() {
getModel().setHostProperty("Bound property");
}
}
This example is a BindingModel
model interface:
public interface BindingModel extends TemplateModel {
void setHostProperty(String propertyValue);
String getHostProperty();
}
Binding Text Content
To bind text content in a JavaScript Polymer template, use the \[[propertyName]]
syntax inside a tag. Double square brackets (i.e., [[ ]]
) mark a one-way binding.
This example shows binding text content in a JavaScript Polymer template:
class MyTemplate extends PolymerElement {
static get template() {
return html`<div>[[hostProperty]]</div>`;
}
static get is() {
return 'my-template';
}
}
customElements.define(MyTemplate.is, MyTemplate);
Binding Property Values
To set an element property value based on a model, use the property name in the attribute format. You would do this by using the dash-case format, sometimes referred to as kebab case; for example, my-property-name
(not camel case, myPropertyName
).
For example, setting an element property based on a model in a JavaScript Polymer template might look like this:
return html`<my-element my-property="[[hostProperty]]"></my-element>`;
This binds to the target property, myProperty
, on <my-element>
.
Using name="[[binding]]"
specifies that the element property named name
should get its value from the model property named binding
. Whereas, name="binding"
(i.e., without brackets) specifies that the element attribute named name
should have the value binding
, regardless of any value in the model.
Polymer can’t directly bind certain common native element properties because the binding causes issues on one or more browsers. In these cases, you can use instead attribute bindings. See the Polymer Project page on Native properties that don’t support property binding for more information.
Binding Attribute Values
The binding <div something="[[hostProperty]]"></div>
is bound to the property something
because the property can typically be changed on the fly, while the attribute is typically used only for the initial value.
To explicitly bind to an attribute, use the attribute name followed by a dollar sign (i.e., $
).
For example, binding to an attribute in a JavaScript Polymer template would be like this:
return html`<div something$="[[hostProperty]]"></div>`;
Or it might look like this:
return html`<a href$="[[hostProperty]]"></a>`;
Two-Way vs. One-Way Bindings
Text surrounded by double curly brackets (i.e., {{ }}
) or double square brackets (i.e., [[ ]]
) delimiters identifies the host data that’s bound. Double curly brackets mark two-way bindings – both server-to-client and client-to-server data flow. Whereas, double square brackets mark one-way bindings – only server-to-client data flow.
Creating Two-Way Data Bindings
For two-way data binding, data flows in both directions – client-to-server and server-to-client.
To demonstrate, create a two-way binding model class with some fields. Create a Java template class that sets default values for the model, and adds listeners for save
and reset
events. Also, you’ll need an associated JavaScript Polymer template.
In the example here, there’s a TwoWayBindingModel
with name
, accepted
, and size
fields.
public interface TwoWayBindingModel extends TemplateModel {
void setName(String name);
String getName();
void setAccepted(Boolean accepted);
Boolean getAccepted();
void setSize(String size);
String getSize();
}
In this next example, there’s a PolymerTwoWayBindingTemplate
Java template class that defines save
and reset
event property change listeners, and sets default values for the name
, accepted
and size
fields.
@Tag("two-way-template")
@JsModule("./com/example/two-way-template.js")
public class PolymerTwoWayBindingTemplate
extends PolymerTemplate<TwoWayBindingModel> {
public PolymerTwoWayBindingTemplate() {
reset();
getElement().addPropertyChangeListener("name", event -> System.out
.println("Name is set to: " + getModel().getName()));
getElement().addPropertyChangeListener("accepted",
event -> System.out.println("isAccepted is set to: "
+ getModel().getAccepted()));
getElement().addPropertyChangeListener("size", event -> System.out
.println("Size is set to: " + getModel().getSize()));
}
@EventHandler
private void reset() {
getModel().setName("John");
getModel().setAccepted(false);
getModel().setSize("medium");
}
}
The Element::addPropertyChangeListener()
method gets immediate updates when the property values change. As an alternative, you could define an @EventHandler
method on the server side and add appropriate event handlers in the template. On the client, the following methods are used to bind the model data. See the JavaScript template that follows it.
-
name
string is bound to an input using:-
native input element
-
Polymer element
paper-input
-
-
accepted
boolean is bound to a checkbox using:-
native checkbox input
-
Polymer element
paper-checkbox
-
-
size
string is bound to a select element using:-
native select
-
Polymer elements
paper-radio-group
andpaper-radio-button
-
Note
|
Native elements need to specify a custom-change event name in the annotation using the |
This example shows a Polymer JavaScript template:
class TwoWayBinding extends PolymerElement {
static get template() {
return html`
<table>
<tr>
<td>Paper name:</td>
<td>
<paper-input value="{{name}}"></paper-input>
</td>
</tr>
<tr>
<td>Input name:</td>
<td>
<input value="{{name::input}}">
</td>
</tr>
<tr>
<td>Change name:</td>
<td>
<input value="{{name::change}}">
</td>
</tr>
<tr>
<td>Input accepted:</td>
<td>
<input type="checkbox" checked="{{accepted::change}}">
</td>
</tr>
<tr>
<td>Polymer accepted:</td>
<td>
<paper-checkbox checked="{{accepted}}"></paper-checkbox>
</td>
</tr>
<tr>
<td>Size:</td>
<td>
<paper-radio-group selected="{{size}}">
<paper-radio-button name="small">Small</paper-radio-button>
<paper-radio-button name="medium">Medium</paper-radio-button>
<paper-radio-button name="large">Large</paper-radio-button>
</paper-radio-group>
</td>
</tr>
<tr>
<td>Size:</td>
<td>
<select value="{{size::change}}">
<option value="small">Small</option>
<option value="medium">Medium</option>
<option value="large">Large</option>
</select>
</td>
</tr>
</table>
<div>
<button on-click="reset">Reset values</button>
</div>
<slot></slot>
`;
}
static get is() {
return 'two-way-template';
}
}
customElements.define(TwoWayBinding.is, TwoWayBinding);
This uses two-way bindings for each element. Some elements bind to the same property. For example, when the value for name
is changed in the paper-input
element, the new value reflects in both Input name
and Change name
.
The two input bindings, Input name
and Change name
, work in slightly different ways: Input name
binds using {{name::input}}
and Change name
binds using {{name::change}}
. The given target-change-event
lets Polymer know which event to listen to for change notifications. The functional difference is that ::input
updates during typing, and ::change
updates when the value of the field changes, for example, an onBlur
event or Enter
key press.
Here’s the template representation in the browser:
For information on the <slot></slot>
element, see Dynamically Adding Server-side Components to Templates.
9C215333-D417-4BB0-A29B-8DE04AADAF17