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:
package com.company.demo.mentionjs;
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;
@JavaScript({
"vaadin://mentionjs/bootstrap-typeahead.js",
"vaadin://mentionjs/mention.js",
"vaadin://mentionjs/mentionjs-extension.js"
})
@StyleSheet("vaadin://mentionjs/bootstrap.min.css")
@WebJarResource({
"jquery:jquery.min.js"
})
public class MentionJsExtension extends AbstractJavaScriptExtension {
// extension requires Vaadin TextArea
public MentionJsExtension(com.vaadin.ui.TextArea target) {
super(target);
}
// API of our extension
public void setUsers(List<String> logins) {
getState().logins = logins;
}
// override getState methods to enable custom state POJO
@Override
protected MentionJsState getState() {
return (MentionJsState) super.getState();
}
@Override
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
$(textArea).mention({
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 {
@Inject
protected TextArea<String> messageArea;
@Subscribe
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: GitHub - cuba-labs/user-mentions: How to enable Twitter-like user mentions in TextArea using Mention.js
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: Integrating JavaScript Components and Extensions | Client-Server Integration | Framework | Vaadin 8 Docs