Integration of third-party Vaadin components is described in Section 4.5.10.1, “Using Third-Party Vaadin Components”.
Below is the example of using the Stepper component, available at http://vaadin.com/addon/stepper. This component allows changing text field value in steps using the keyboard, mouse scroll or built-in up/down buttons.
-
Assuming that the project has a
Customer
entity with a String-typename
attribute. An editor screen (customer-edit.xml
) was created in the web module with the following layout:<layout expand="windowActions" spacing="true"> <fieldGroup id="fieldGroup" datasource="customerDs"> <column width="250px"> <field id="name"/> </column> </fieldGroup> <iframe id="windowActions" screen="editWindowActions"/> </layout>
Our task is to add an
Integer
-typescore
attribute for step editing to the screen. -
Add the
score
attribute to theCustomer
entity in CUBA Studio:@Column(name = "SCORE") protected Integer score; public void setScore(Integer score) { this.score = score; } public Integer getScore() { return score; }
Generate DB scripts and run the database update.
-
Run the Project properties section of the Studio navigation panel.
command from the -
Add a dependency on the component add-on to the web module in the project’s build.gradle:
configure(webModule) { ... dependencies { ... compile("org.vaadin.addons:stepper:2.1.2") }
-
Re-create the IDE project files (
menu item). -
Include the add-on widget set in the
AppWidgetSet.gwt.xml
of the project’s web-toolkit module after the platform widget set:<module> <inherits name="com.haulmont.cuba.web.toolkit.ui.WidgetSet" /> <inherits name="org.vaadin.risto.stepper.widgetset.StepperWidgetset" /> <set-property name="user.agent" value="safari" />
Building of widgets can be accelerated by setting the
user.agent
property. In this example, the widget set will be built only for WebKit-based browsers: Chrome, Safari, etc. -
Add a custom
score
field to the fieldGroup component in thecustomer-edit.xml
descriptor:<fieldGroup id="fieldGroup" datasource="customerDs"> <column width="250px"> <field id="name"/> <field id="score" custom="true" caption="Score"/> </column> </fieldGroup>
-
Add the following code to the
CustomerEdit
screen controller:public class CustomerEdit extends AbstractEditor<Customer> { @Inject private ComponentsFactory componentsFactory; @Inject private FieldGroup fieldGroup; private IntStepper stepper = new IntStepper(); @Override public void init(Map<String, Object> params) { fieldGroup.addCustomField("score", new FieldGroup.CustomFieldGenerator() { @Override public Component generateField(final Datasource datasource, final String propertyId) { Component box = componentsFactory.createComponent(BoxLayout.VBOX); com.vaadin.ui.Layout layout = WebComponentsHelper.unwrap(box); layout.addComponent(stepper); stepper.setSizeFull(); stepper.addValueChangeListener(new Property.ValueChangeListener() { @Override public void valueChange(Property.ValueChangeEvent event) { datasource.getItem().setValue(propertyId, event.getProperty().getValue()); } }); return box; } }); } @Override protected void postInit() { stepper.setValue(getItem().getScore()); } }
An instance of the component from the add-on is created in the
stepper
field. Theinit()
method initializes the customscore
field. TheComponentsFactory
creates an instance of BoxLayout, retrieves a link to the Vaadin container via WebComponentsHelper, and adds the new component to it. TheBoxLayout
is then returned to be used in the custom field.Component data binding is implemented by setting its current value from the edited
Customer
in thepostInit()
method. Additionally, the corresponding entity attribute is updated through the implemented value change listener, when the user changes the value. -
The new component can be used in any part of the screen outside of the
FieldGroup
. In order to do this, declare a container in the XML-descriptor:<hbox id="scoreBox" spacing="true"> <label value="Score"/> </hbox>
Inject the container in the screen controller, retrieve a link to the Vaadin container and add the component to it:
public class CustomerEdit extends AbstractEditor<Customer> { @Inject private BoxLayout scoreBox; private IntStepper stepper = new IntStepper(); @Override public void init(Map<String, Object> params) { com.vaadin.ui.Layout box = WebComponentsHelper.unwrap(scoreBox); box.addComponent(stepper); stepper.addValueChangeListener(new Property.ValueChangeListener() { @Override public void valueChange(Property.ValueChangeEvent event) { getItem().setValue("score", event.getProperty().getValue()); } }); } @Override protected void postInit() { stepper.setValue(getItem().getScore()); } }
Data binding is implemented in the same way as described above.
-
To adapt the component style, create a theme extension in the project. Run the Project properties section of the Studio navigation panel. After that, open the
command in thethemes/havana/havana-ext.scss
file in the web module and add the following code:@import "../havana/havana"; @mixin havana-ext { @include havana; /* Basic styles for stepper */ .v-stepper { /* Use box-sizing: border-box; for all browsers */ @include box-defaults; height: 25px; border: 0; /* Use theme fonts */ font-family: $theme_fonts; } /* Basic styles for inner text box */ .v-stepper input[type="text"] { /* Use box-sizing: border-box; for all browsers */ @include box-defaults; height: 25px; padding: 1px; outline: 0; margin: 0; /* Use border color from theme */ border: 1px solid $theme_fieldBorderColor; } /* Focused styles */ .v-stepper.v-stepper input[type="text"]:focus { /* Use focused border color from theme */ border-color: $theme_fieldFocusedBorderColor; /* hide default focus outline */ outline: 0; } /* Readonly styles */ .v-readonly.v-stepper input[type="text"], .v-readonly.v-stepper input[type="text"]:focus { /* Use readonly border color from theme */ border-color: $theme_fieldReadonlyBorderColor; } }