Hi! I have Editor screen with TextArea:
<vbox id="commentBoxSample" stylename="rcg-gt-block" spacing="true" width="100%" > <textArea id="comment" property="comment" width="100%" height="90px" datasource="productDs" visible="false"/> </vbox>
Here is controller:
public class ProductEdit extends AbstractEditor<Product> { @Inject protected VBoxLayout commentBoxSample; @Inject private Datasource<Product> productDs; @Inject private DataManager dataManager; @Inject private Metadata metadata; private List<User> users = new ArrayList<>(); @Override protected void postInit() { super.postInit(); LoadContext<User> userLoadContext = LoadContext.create(User.class); userLoadContext.setView("_local") .setQuery(LoadContext.createQuery("select e from sec$User e")); users = ProductEdit.this.dataManager.loadList(userLoadContext); // loads 40000+ users configureMention(); } protected void configureMention() { List<MentionUser> collect = users.stream() .map(user -> { MentionUser mentionUser = new MentionUser(user.getLogin(), user.getFirstName(), "http://placekitten.com/25/25"); return mentionUser; }) .collect(Collectors.toList()); List<MentionUser> subList = collect.subList(0, 5); Component mentionArea = componentsFactory.createComponent(VBoxLayout.class); mentionArea.setId("mentionArea"); Layout vaadinTextArea = (Layout) WebComponentsHelper.unwrap(mentionArea); MentionServerComponent mention = new MentionServerComponent(); mention.setLoginValues(subList); mention.setValueChangeListener(new MentionValueChangeListenerImpl()); mention.setContentChangeListener(new MentionValueChangeListenerImpl()); vaadinTextArea.addComponent(mention); commentBoxSample.add(mentionArea); } class MentionValueChangeListenerImpl implements MentionServerComponent.ValueChangeListener, MentionServerComponent.ContentChangeListener { @Override public List<MentionUser> valueChanged(String newValue) { return users.stream() .filter(user -> user.getLogin().toLowerCase().contains(newValue.toLowerCase())) .map(user -> { MentionUser mentionUser = new MentionUser(user.getLogin(), user.getFirstName(), "http://placekitten.com/25/25"); return mentionUser; }) .collect(Collectors.toList()); } @Override public void contentChanged(String content) { ProductEdit.this.comment.setValue(content); } } }
Here is JavaScript connector:
> @JavaScript({"jquery.min.js", "bootstrap-typeahead.js", "mention.js", "mention-connector.js"})
> @StyleSheet({"bootstrap.min.css"})
> public class MentionServerComponent extends AbstractJavaScriptComponent {
> private ValueChangeListener valueChangeListener;
> public interface ValueChangeListener {
> List<MentionUser> valueChanged(String userValue);
> }
>
> private ContentChangeListener contentChangeListener;
> public interface ContentChangeListener {
> void contentChanged(String content);
> }
>
> public MentionServerComponent() {
> addFunction("valueChanged", arguments -> {
> String userMentionValue = arguments.get(0).asString();
> List<MentionUser> usernameValues = valueChangeListener.valueChanged(userMentionValue);
>
> if (usernameValues != null) {
> setLoginValues(usernameValues);
> }
> });
>
> addFunction("writeContent", arguments -> {
> String content = arguments.get(0).asString();
> contentChangeListener.contentChanged(content);
> });
> }
>
> public void setLogins(String[] logins) {
> getState().logins = logins;
> }
>
> public String[] getLogins() {
> return getState().logins;
> }
>
> @Override
> protected MentionState getState() {
> return (MentionState) super.getState();
> }
>
> @Override
> public MentionState getState(boolean markAsDirty) {
> return (MentionState) super.getState(markAsDirty);
> }
>
> public ValueChangeListener getValueChangeListener() {
> return valueChangeListener;
> }
>
> public void setValueChangeListener(ValueChangeListener listener) {
> this.valueChangeListener = listener;
> }
>
> public void setLoginValues(List<MentionUser> logins) {
> getState(false).users = logins.toArray(new MentionUser[0]);
> }
>
> public ContentChangeListener getContentChangeListener() {
> return contentChangeListener;
> }
>
> public void setContentChangeListener(ContentChangeListener contentChangeListener) {
> this.contentChangeListener = contentChangeListener;
> }
>
> }
Here is state:
public class MentionState extends JavaScriptComponentState { public String[] logins; public MentionUser[] users; }
And, JavaScript code:
> com_company_jsdemo_web_toolkit_ui_mention_MentionServerComponent = function () {
> var connector = this;
> var element = connector.getElement();
> $(element).html("" +
> "<div>" +
> "<textarea id='mention'></textarea>" +
> "</div>");
> $(element).css("padding", "5px 10px");
>
> var mentionArea = $("#mention", element);
> mentionArea.css("width", "600px");
>
> mentionArea.bind('input propertychange', function () {
> if (mentionArea) {
> var resultVal = mentionArea.val();
> connector.writeContent(resultVal);
>
> if(mentionArea.val().charAt(0) === '@'){
> resultVal = mentionArea.val().substring(1);
> connector.valueChanged(resultVal);
> }
> }
> });
>
> connector.onStateChange = function () {
> var state = connector.getState();
> var logins = state.users;
> alert(logins.length);
> if (logins) {
> var userList = [];
> for (var i = 0; i < logins.length; i++) {
> userList.push({username: logins[i].username, name: logins[i].name, image: logins[i].image});
> }
>
> $(mentionArea).mention({
> delimiter: '@',
> users: userList,
> typeaheadOpts: {
> items: 10
> }
> });
> }
> }
>
> }
I used JavaScript library from Mention.JS
But, JS side does not see new values of MentionState when it is changed by mentionArea.bind() event listener. The content of MentionState.users changes and new values comes into connector.onStateChange function, but ignores them and it works with old data values. I saw similar example on This topic. But there is nothing about dynamically changing state data. Please, help me)