Skip to content

Commit

Permalink
Fix connector to fully survive attach - detach - reattach cycle
Browse files Browse the repository at this point in the history
  • Loading branch information
TatuLund committed Jan 3, 2024
1 parent 6e246bb commit 8aab0e5
Show file tree
Hide file tree
Showing 3 changed files with 64 additions and 37 deletions.
13 changes: 11 additions & 2 deletions src/main/java/org/vaadin/tinymce/TinyMce.java
Original file line number Diff line number Diff line change
Expand Up @@ -86,8 +86,10 @@ public TinyMce() {
public void setEditorContent(String html) {
this.currentValue = html;
if (initialContentSent) {
runBeforeClientResponse(ui -> getElement()
.callJsFunction("$connector.setEditorContent", html));
runBeforeClientResponse(ui -> {
getElement().callJsFunction("$connector.setEditorContent",
html);
});
} else {
ta.setProperty("innerHTML", html);
}
Expand All @@ -97,6 +99,11 @@ public void setEditorContent(String html) {
protected void onAttach(AttachEvent attachEvent) {
id = UUID.randomUUID().toString();
ta.setAttribute("id", id);
if (!attachEvent.isInitialAttach()) {
// Value after initial attach should be set via TinyMCE JavaScript
// API, otherwise value is not updated upon reattach
initialContentSent = true;
}
ta.setProperty("innerHTML", currentValue);
super.onAttach(attachEvent);
initConnector();
Expand All @@ -117,6 +124,8 @@ private void initConnector() {
ui.getPage().executeJs(
"window.Vaadin.Flow.tinymceConnector.initLazy($0, $1, $2, $3)",
rawConfig, getElement(), ta, config).then(res -> {
// Delay setting flag on first attach, otherwise setting
// initial value on attach does not work
initialContentSent = true;
});
});
Expand Down
50 changes: 29 additions & 21 deletions src/main/resources/META-INF/resources/frontend/tinymceConnector.js
Original file line number Diff line number Diff line change
@@ -1,31 +1,38 @@
window.Vaadin.Flow.tinymceConnector = {
initLazy: function (customConfig, c, ta, options) {
// Check whether the connector was already initialized for the datepicker
// Check whether the connector was already initialized for the editor
var currentValue = ta.innerHTML;

if (c.$connector) {
return;
}

c.$connector = {
// If connector was already set, this is re-attach, remove editor
// and re-init
tinymce.remove();
} else {
// Init connector at first visit
c.$connector = {

setEditorContent : function(html) {
this.editor.setContent(html);
},
setEditorContent : function(html) {
// Delay setting the content, otherwise there is issue during reattach
setTimeout(() => {
currentValue = this.editor.setContent(html, {format : 'html'});
}, 50);
},

replaceSelectionContent : function(html) {
this.editor.selection.setContent(html);
},
replaceSelectionContent : function(html) {
this.editor.selection.setContent(html);
},

focus : function() {
this.editor.focus();
},
focus : function() {
this.editor.focus();
},

setEnabled : function(enabled) {
this.editor.mode.set(enabled ? "design" : "readonly");
}
setEnabled : function(enabled) {
this.editor.mode.set(enabled ? "design" : "readonly");
}

};
};

var currentValue = "";
}

const pushChanges = function() {
c.$server.updateValue(currentValue)
Expand All @@ -42,17 +49,18 @@ window.Vaadin.Flow.tinymceConnector = {
baseconfig['setup'] = function(ed) {
c.$connector.editor = ed;
ed.on('setContent', function(e) {
currentValue = ed.getContent();
currentValue = ed.getContent();
});
ed.on('change', function(e) {
currentValue = ed.getContent();
currentValue = ed.getContent();
});
ed.on('blur', function(e) {
currentValue = ed.getContent();
pushChanges();
});
};

// Allways re-init editor
tinymce.init(baseconfig);
}
}
38 changes: 24 additions & 14 deletions src/test/java/org/vaadin/tinymce/OnAttachTest.java
Original file line number Diff line number Diff line change
Expand Up @@ -5,10 +5,13 @@
import java.util.Random;

import com.vaadin.flow.component.AttachEvent;
import com.vaadin.flow.component.Composite;
import com.vaadin.flow.component.DetachEvent;
import com.vaadin.flow.component.button.Button;
import com.vaadin.flow.component.html.Div;
import com.vaadin.flow.component.notification.Notification;
import com.vaadin.flow.component.orderedlayout.VerticalLayout;
import com.vaadin.flow.internal.ReflectTools;
import com.vaadin.flow.router.PreserveOnRefresh;
import com.vaadin.flow.router.Route;

Expand All @@ -22,46 +25,53 @@ public OnAttachTest() {
Button button = new Button("Switch");
List<String> values = Arrays.asList("<b>Value 1</b>", "<i>Value 2</i>",
"<span style='text-decoration: underline;'>Value 3</span>");
Button button2 = new Button("Preset");

EditorView editor = new EditorView(values.get(i));
button2.addClickListener(e-> {
editor.setValue("<p style='color: blue'>Blue</p>", true);
});

button.addClickListener(e -> {
this.removeAll();
i++;
if (i > 2)
i = 0;
editor.setValue(values.get(i));
add(button, editor);
editor.setValue(values.get(i), false);
add(button, button2, editor);
});
add(button, editor);
add(button, button2, editor);
}

public static class EditorView extends Div {
public static class EditorView extends Composite<TinyMce> {
private String value;
private TinyMce tinyMce;

public EditorView(String value) {
this.value = value;
getContent().configurePlugin(true, Plugin.TABLE).configureToolbar(true,
Toolbar.TABLE);
getContent().addValueChangeListener(e -> {
this.value = e.getValue();
});
}

public void setValue(String value) {
public void setValue(String value, boolean immediate) {
if (immediate) {
Notification.show(getContent().getValue());
getContent().setValue(value);
}
this.value = value;
}

@Override
protected void onAttach(AttachEvent attachEvent) {
super.onAttach(attachEvent);
tinyMce = new TinyMce();
tinyMce.addValueChangeListener(e -> {
value = e.getValue();
});
tinyMce.configurePlugin(true, Plugin.TABLE).configureToolbar(true,
Toolbar.TABLE);
add(tinyMce);
tinyMce.setValue(value);
getContent().setValue(value);
}

@Override
protected void onDetach(DetachEvent detachEvent) {
remove(tinyMce);
}
}
}

0 comments on commit 8aab0e5

Please sign in to comment.