Enabled State

Components that allow user interaction, such as TextField or Button, can have three different enabled states:

  • Enabled: An enabled component allows the user to interact with it. This is the default state.

  • Explicitly disabled: A component is explicitly disabled when setEnabled(false) is called directly on it. The user cannot interact with the component, and communication from the client to the server is blocked.

  • Implicitly disabled: A component is implicitly disabled when it is a child of a explicitly disabled container. The component behaves exactly like an explicitly disabled component, except it is automatically enabled again as soon as it detaches from the disabled container.

Explicitly Enabling and Disabling Components

Any component that implements the HasEnabled interface can be explicitly enabled or disabled.

Example: Disabling a component using the component.setEnabled method.

Java

  1. TextField name = new TextField("Name");
  2. name.setEnabled(false);
  • This disables the name field:

    • Users cannot interact with it, and

    • Events from the client to the server are blocked.

  • The server does not handle status updates from the component, even if the component is changed manually on the browser, for example by a client-side script or via a developer console.

Example: Disabling all components in a container by using the same API:

Java

  1. FormLayout form = new FormLayout();
  2. TextField name = new TextField("Name");
  3. TextField email = new TextField("E-mail");
  4. Button submit = new Button("Submit");
  5. form.add(name, email, submit);
  6. // all children are implicitly disabled
  7. form.setEnabled(false);
  8. System.out.println(name.isEnabled()); // prints false

Implicitly Enabled and Disabled Components

When an implicitly disabled component is detached from a disabled container, it is automatically enabled again. Similarly, if an enabled component is attached to a disabled container, it is automatically implicitly disabled.

Examples: Implicitly enabled and disabled components

Java

  1. FormLayout form = new FormLayout();
  2. form.setEnabled(false); // the entire form is disabled
  3. TextField name = new TextField("Name");
  4. // prints true, since it is not attached yet
  5. System.out.println(name.isEnabled());
  6. Button submit = new Button("Submit");
  7. // the submit button is explicitly disabled
  8. submit.setEnabled(false);
  9. System.out.println(submit.isEnabled()); // prints false
  10. form.add(name, submit); // attaches children
  11. System.out.println(name.isEnabled()); // prints false
  12. System.out.println(submit.isEnabled()); // prints false
  13. form.remove(name); // the name field gets detached
  14. System.out.println(name.isEnabled()); // prints true
  15. form.remove(submit); // the submit button gets detached
  16. // prints false, since it was explicitly disabled
  17. System.out.println(submit.isEnabled());

Overriding Default Disabled Behavior

By default, disabled components do not allow user interaction from the client side. However, it is sometimes necessary for complex (composite) components to remain partially functional, even in the disabled state. For example, you may want to only fully enable a registration form after a user selects a checkbox to accept a license agreement.

Enabling Property Changes

You can override the default disabled behavior by enabling certain RPC-client-side calls that would normally be blocked for disabled components.

The first way to do this is to use the synchronizeProperty method with the DisabledUpdateMode.ALWAYS argument value.

Example: This Polymer template component controls its own enabled state via the checkbox. The checkbox is never disabled, and it enables and disables the component.

Java

  1. @Tag("registration-form")
  2. @JsModule("./src/registration-form.js")
  3. public class RegistrationForm
  4. extends PolymerTemplate<TemplateModel>
  5. implements HasEnabled {
  6. @Id
  7. private TextField name;
  8. @Id
  9. private TextField email;
  10. @Id
  11. private Button submit;
  12. @Id
  13. private Element enable;
  14. public RegistrationForm() {
  15. enable.synchronizeProperty("checked",
  16. "checked-changed",
  17. DisabledUpdateMode.ALWAYS);
  18. enable.addPropertyChangeListener("checked",
  19. this::handleEnabled);
  20. setEnabled(false);
  21. }
  22. private void handleEnabled(
  23. PropertyChangeEvent event) {
  24. setEnabled((Boolean) event.getValue());
  25. }
  26. @EventHandler
  27. private void register() {
  28. String userName = name.getValue();
  29. String userEmail = email.getValue();
  30. System.out.println("Register user with name='"
  31. + userName
  32. + "' and email='" + userEmail + "'");
  33. }
  34. }

Here is its template file:

js

  1. class RegistrationForm extends PolymerElement {
  2. static get template() {
  3. return html`
  4. <vaadin-text-field id='name'>
  5. {{name}}
  6. </vaadin-text-field>
  7. <vaadin-text-field id='email'>
  8. {{email}}
  9. </vaadin-text-field>
  10. <vaadin-button id='submit'
  11. on-click='register'>
  12. Register
  13. </vaadin-button>
  14. <vaadin-checkbox id='enable'>
  15. Accept License Agreement
  16. </vaadin-checkbox>`;
  17. }
  18. static get is() {
  19. return 'registration-form';
  20. }
  21. }
  22. customElements.define(RegistrationForm.is,
  23. RegistrationForm);
  • The checkbox is implicitly disabled if the template (which is its parent) is disabled. As a result, no RPC is allowed for the checkbox.

  • The synchronizeProperty method (with extra arguments) is used to synchronize the checked property.

    • The argument, DisabledUpdateMode.ALWAYS, is an enum value that allows updates for this property, even if the element is disabled.
  • The folowing RPC communications are blocked for the disabled element:

    • Property changes.

    • DOM events.

    • Event handler methods (annotated with @EventHandler). For example, the register() method is an event handler method that is blocked when the component is disabled.

    • Client delegate methods (annotated with @ClientCallable).

As an alternative, you can use the @Synchronize annotation with the DisabledUpdateMode.ALWAYS argument value.

Example: Using the @Synchronize annotation for the property getter in your component.

Java

  1. @Synchronize(property = "prop", value = "prop-changed",
  2. allowUpdates = DisabledUpdateMode.ALWAYS)
  3. public String getProp() {
  4. return getElement().getProperty("prop");
  5. }

Enabling DOM Events

There are two ways to enable DOM events. You can use:

  1. An addEventListener overload method in the Element API, or

  2. The @DomEvent annotation.

Example: Unblocking a DOM event for a disabled element using the addEventListener overload method that accepts the DisabledUpdateMode.ALWAYS parameter.

Java

  1. public Notification() {
  2. getElement().addEventListener("opened-changed",
  3. event -> System.out.println("Opened"))
  4. .setDisabledUpdateMode(DisabledUpdateMode.ALWAYS);
  5. }

Example: Unblocking a DOM event for a disabled component using the @DomEvent annotation with the parameter value allowUpdates = DisabledUpdateMode.ALWAYS ):

Java

  1. @DomEvent(value = "click",
  2. allowUpdates = DisabledUpdateMode.ALWAYS)
  3. public class CustomEvent
  4. extends ComponentEvent<Component> {
  5. }

Enabling Server-Handler Methods

If there are server-handler methods annotated with @ClientCallable or @EventHandler, you can unblock them for disabled components by specifying DisabledUpdateMode.ALWAYS as a value.

Example: Specifying DisabledUpdateMode.ALWAYS

Java

  1. @EventHandler(DisabledUpdateMode.ALWAYS)
  2. private void eventHandler() {
  3. }
  4. @ClientCallable(DisabledUpdateMode.ALWAYS)
  5. private void clientRequest() {
  6. }