pejrich
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?
Most Liked
riverside
Hopefully this helps out anyone in the future. Based on the tip found here. For my use case, what i did was:
- Set up a form in a live component.
def render(assigns) do
~L"""
<div class="form_container">
<%= f = form for @changeset,
#,
phx_target: @myself,
phx_change: "validate_form" ,
id: "richtext_form"
%>
<div
phx-hook="RichText"
phx-update="ignore"
phx-target="<%= @myself %>"
id="richtext_container"
>
<%= textarea f,
:the_content,
value: @clientside_richtext_input
%>
</div>
</form>
</div>
"""
end
Reason being is i still want to validate the form input on the server side. But the pushing the params after a validation function in the returning {:noreply, socket |> ...} kept on failing and the data being put into to the rich text wasn’t stored anywhere. Which led to:
- Create two handle events. One for the form validation, the other to handle the clientside hook and pass the data into an assign that will be set as the value for the
textarea.
def handle_event(
"validate_form",
%{"richtext_form" => params},
socket) do
{:noreply, socket |> validate_form(params)}
end
def handle_event(
"handle_clientside_richtext",
%{"richtext_data" => richtext_data},
socket) do
{:noreply,
socket
|> assign_form(:clientside_richtext_input, richtext_data)
|> push_event("richtext_event", %{richtext_data: richtext_data})}
end
This is so that the richtext data can be stored by cycling back and forth between the client and backend for when the live component is updated. Now for the same thing inside the JS code.
- In a hook object do
const RichText = {
mounted(){
init(this.el.querySelector("#richtext_form_the_content"))
},
updated(){
const textArea = init(this.el.querySelector("#richtext_form_the_content"));
textArea.codemirror.on("change", ( ) => {
this.pushEventTo(
this.el,
"handle_clientside_richtext",
{richtext_data: textArea.value()}
);
this.handleEvent(
"richtext_event",
(richtext_data) => textArea.value(richtext_data)
)
})
}
}
The logic is in the updated function since mounted rich text area gets erased right away.
- And finally to have easyMDE be usable do
import easyMDE from "easyMDE";
const init = (element) => new easyMDE({
element: element,
forceSync: true
})
The forceSync: true is for the data to be set as the textarea value on the clientside and play well with the backend.
It took a few days of looking back and forth at different examples, reading the forum, rereading the docs, looking at source code, and feeling dumb. This is the simplest solution that i can think of once it all clicked.
*edit typo fix: phx-update: "TextEditor" to phx-hook: "RichText"
Popular in Questions
Other popular topics
Latest Phoenix Threads
Categories:
Sub Categories:
Forums
Popular Tags
- #ecto
- #liveview
- #troubleshooting
- #learning-elixir
- #deployment
- #library
- #erlang
- #testing
- #genserver
- #mix
- #absinthe
- #remote-other
- #otp
- #plug
- #how-to-question
- #macros
- #postgres
- #channels
- #elixirconf
- #exunit
- #discussion
- #code-sync
- #javascript
- #podcasts
- #onsite
- #dialyzer
- #docker
- #authentication
- #umbrella
- #full-time-contract
- #podcasts-by-brainlid
- #ecto-query
- #elixir-ls
- #phoenix_html
- #iex
- #blog-post
- #graphql
- #genstage
- #ai
- #websockets
- #supervisor
- #elixirconf-us
- #advent-of-code
- #distillery
- #processes
- #forms
- #api
- #metaprogramming
- #security
- #hex









