How to show autocomplete for user mentions in TextArea

Sometimes we need to implement Twitter-like user mentions in text areas:


Here you will see how to integrate a third-party JavaScript extension, such as Mention.js.

First of all, you will need to create VAADIN directory in modules/web/web and copy all your JS/CSS assets there.


Then declare Java class for your extension in web module sources:


import com.haulmont.cuba.web.widgets.WebJarResource;
import com.vaadin.annotations.JavaScript;
import com.vaadin.annotations.StyleSheet;
import com.vaadin.server.AbstractJavaScriptExtension;

import java.util.List;

public class MentionJsExtension extends AbstractJavaScriptExtension {
    // extension requires Vaadin TextArea
    public MentionJsExtension(com.vaadin.ui.TextArea target) {

    // API of our extension
    public void setUsers(List<String> logins) {
        getState().logins = logins;

    // override getState methods to enable custom state POJO
    protected MentionJsState getState() {
        return (MentionJsState) super.getState();

    protected MentionJsState getState(boolean markAsDirty) {
        return (MentionJsState) super.getState(markAsDirty);

Here we define all the required CSS/JS resources using @JavaScript and @StyleSheet annotations. Also, we need custom POJO that will represent state of the extension (it will be passed to JS side):

public class MentionJsState extends JavaScriptExtensionState {
    public List<String> logins;

After that we can define JS side in mentionjs-extension.js:

// entry point of client side code
// function should be named as FQN of the corresponding Java class
window.com_company_demo_mentionjs_MentionJsExtension = function () {
    var self = this;
    var textArea = self.getElement(self.getParentId());

    // subscribe on state change from server
    self.onStateChange = function () {
        var logins = this.getState().logins;
        if (logins) {
            var users = [];
            for (var i = 0; i < logins.length; i++) {
                users.push({username: logins[i]});
            // call mention JS code
                delimiter: '@',
                users: users

This code will be loaded and executed after JavaScript extension added to TextArea.

Now, we can enable extension in UI screen as follows:

public class DemoScreen extends Screen {
    protected TextArea<String> messageArea;

    protected void onInit(InitEvent event) {
        // get Vaadin UI component from CUBA class
        com.vaadin.ui.TextArea vTextArea = messageArea.unwrap(com.vaadin.ui.TextArea.class);

        // enable extension
        MentionJsExtension extension = new MentionJsExtension(vTextArea);
        extension.setUsers(Arrays.asList("Peter", "Lilith", "John", "Mathew", "Alex"));

It will look like:

You can find the sample code here:

JavaScript extensions enable you to apply JS code to the existing UI components, e.g. inputs, labels, buttons, etc. Read more about JS integration here: