--- title: Component and UI Extensions order: 7 layout: page --- [[gwt.extension]] = Component and UI Extensions Adding features to existing components by extending them by inheritance creates a problem when you want to combine such features. For example, one add-on could add spell-check to a [classname]#TextField#, while another could add client-side validation. Combining such add-on features would be difficult if not impossible. You might also want to add a feature to several or even to all components, but extending all of them by inheritance is not really an option. Vaadin includes a component plug-in mechanism for these purposes. Such plug-ins are simply called __extensions__. Also a UI can be extended in a similar fashion. In fact, some Vaadin features such as the JavaScript execution are UI extensions. Implementing an extension requires defining a server-side extension class and a client-side connector. An extension can have a shared state with the connector and use RPC, just like a component could. [[gwt.extension.server-side]] == Server-Side Extension API The server-side API for an extension consists of class that extends (in the Java sense) the [classname]#AbstractExtension# class. It typically has an __extend()__ method, a constructor, or a static helper method that takes the extended component or UI as a parameter and passes it to __super.extend()__. For example, let us have a trivial example with an extension that takes no special parameters, and illustrates the three alternative APIs: [source,java] ---- public class CapsLockWarning extends AbstractExtension { // You could pass it in the constructor public CapsLockWarning(PasswordField field) { super.extend(field); } // Or in an extend() method public void extend(PasswordField field) { super.extend(field); } // Or with a static helper public static void addTo(PasswordField field) { new CapsLockWarning().extend(field); } // NOTE: you only need one of the above, not all of them } ---- The extension could then be added to a component as follows: [source,java] ---- PasswordField password = new PasswordField("Give it"); // Use the constructor new CapsLockWarning(password); // ... or with the extend() method new CapsLockWarning().extend(password); // ... or with the static helper CapsLockWarning.addTo(password); layout.addComponent(password); ---- Adding a feature in such a "reverse" way is a bit unusual in the Vaadin API, but allows type safety for extensions, as the method can limit the target type to which the extension can be applied, and whether it is a regular component or a UI. [[gwt.extension.connector]] == Extension Connectors An extension does not have a corresponding widget on the client-side, but only an extension connector that extends the [classname]#AbstractExtensionConnector# class. The server-side extension class is specified with a [literal]#++@Connect++# annotation, just like in component connectors. An extension connector needs to implement the [methodname]#extend()# method, which allows hooking to the extended component. The normal extension mechanism is to modify the extended component as needed and add event handlers to it to handle user interaction. An extension connector can share a state with the server-side extension as well as make RPC calls, just like with components. In the following example, we implement a "Caps Lock warning" extension. It listens for changes in Caps Lock state and displays a floating warning element over the extended component if the Caps Lock is on. [source,java] ---- @Connect(CapsLockWarning.class) public class CapsLockWarningConnector extends AbstractExtensionConnector { @Override protected void extend(ServerConnector target) { // Get the extended widget final Widget pw = ((ComponentConnector) target).getWidget(); // Preparations for the added feature final VOverlay warning = new VOverlay(); warning.setOwner(pw); warning.add(new HTML("Caps Lock is enabled!")); // Add an event handler pw.addDomHandler(new KeyPressHandler() { public void onKeyPress(KeyPressEvent event) { if (isEnabled() && isCapsLockOn(event)) { warning.showRelativeTo(passwordWidget); } else { warning.hide(); } } }, KeyPressEvent.getType()); } private boolean isCapsLockOn(KeyPressEvent e) { return e.isShiftKeyDown() ^ Character.isUpperCase(e.getCharCode()); } } ---- The [methodname]#extend()# method gets the connector of the extended component as the parameter, in the above example a [classname]#PasswordFieldConnector#. It can access the widget with the [methodname]#getWidget()#. An extension connector needs to be included in a widget set. The class must therefore be defined under the [filename]#client# package of a widget set, just like with component connectors.