How to add JS loaded textarea with LiveView form?

I’m trying to use this WYSIWYG Markdown editor in my live view form https://github.com/sparksuite/simplemde-markdown-editor (Does anyone know which editor Elixir Forum uses, I want something like this).

Here’s my form

<div class="message_form" style="height: 100px;">
        <%= form_for :message, "#", [phx_change: :typing, phx_submit: :save], fn f -> %>
          <%= textarea f, :text, id: "wysiwyg", phx_hook: "messageTextarea" %>
          <%= submit "Save" %>
        <% end %>
      </div>

Here’s my JS

Hooks.messageTextarea = {
  mounted() {
    new SimpleMDE({ element: document.getElementById("wysiwyg") });
  },
  updated() {
    new SimpleMDE({ element: document.getElementById("wysiwyg") });
  },

The editor appears when the page loads, but when the first character is typed, there is a reload, the editor appears again, but there’s no text in it. If I log the events, I seem to get a bunch of beforeUpdate and updated events firing. How can I keep my events, but stop it from reloading the text area on each character typed?

You likely want to set the textarea to phx-update="ignore" and not reinitialize SimpleMDE. Also instead of document.getElementById("wysiwyg") you could just use this.el.

Putting phx_update: "ignore" on the textarea didn’t do anything. It did work if I put phx_update: "ignore" on the form itself. However then the form doesn’t reset after submitting.

You can try putting the textarea in a wrapping element like a div and only make this one be phx_update: "ignore".

If I do that, it still doesn’t reset the text area to blank after submitting. I don’t mind that, as long as I can trigger something after saving to clear the textarea.

Yeah, this is the place where you’ll notice the problem of having to places trying to be the source of truth. The only “trigger” your liveview will get it that the updated() part of your hook is called.

Presumably after each “change” event is fired, LiveView does something and reloads the text area. Is there anyway to hook into that update and only update the value of the text area, instead of completely reloading the element?

Nope, the server doesn’t send structured updates. It just sends optimized template diffs.

I see. I guess I can either have the WYSIWYG editor, or the user_is_typing indicator, but not both. Hmm. Maybe i can hack around it with some JS.

Is there a way to manually send a phx event from JS? If I put phx-change="typing" on something, that doesn’t work if my JS lib replaces the element. Is there a way I can listen to changes via the 3rd party lib (I know how to do this part), and then trigger events to get sent via phx? Kinda like in channels. channel.push("typing")

pushEvent is what you are looking for I think - documented here: https://hexdocs.pm/phoenix_live_view/Phoenix.LiveView.html#module-js-interop-and-client-controlled-dom

What a coincidence, I just visited the forum to post something else and saw your post. I’m also using this editor in my app.

A question: Where is your form and how are you loading the editor? Mine is in a live_modal. The only way I could make the editor (kinda) work was by placing a <script> tag inside a phx-ignore element. It doesn’t always load, though, and I don’t know why.

And a tip: SimpleMDE hasn’t been maintained in a long time. Use EasyMDE instead!

hey @wowlixir, were you able to make it work? how did you export the textarea in your template? i can´t get it to work