The hook:
import Trix from "trix";
export default {
mounted() {
const element = document.querySelector("trix-editor");
element.editor.element.addEventListener("trix-change", (e) => {
this.el.dispatchEvent(new Event("change", { bubbles: true }));
});
element.editor.element.addEventListener("trix-initialize", () => {
element.editor.element.focus();
var length = element.editor.getDocument().toString().length;
window.setTimeout(() => {
element.editor.setSelectedRange(length, length);
}, 1);
});
this.handleEvent("updateContent", (data) => {
element.editor.loadHTML(data.content || "");
});
},
};
(the hook can be simplified, I use the setTimeout because in one of my forms there’s an auto-save feature that sends an event to the LV after a given period of time and if the user is typing on the editor while the auto-save event fires the cursor was being reset to the beginning of the text, this works around it)
The HTML:
<div>
<%= label(f, :body, gettext("Body")) %>
<%= hidden_input(f, :body, phx_hook: "TrixEditor") %>
<div id="richtext" phx-update="ignore">
<trix-editor input={input_id(f, :body)} class="trix-content">
</trix-editor>
</div>
<%= error_tag(f, :body) %>
</div>