Live View causing issues with element-targeted javascript

Hello elixir community,

I’ve just started using live view and it’s great so far, however there’s one problem i’m not sure how to fix. At the moment, i have several .js files in assets/js/ which instantiate on an element (e.g. typehead, which instantiates on an element in the following fashion)

$('.typeahead').typeahead({
  minLength: 3,
  highlight: true
},
{
  name: 'my-dataset',
  source: mySource
});

I think this issue exists for all types of js libraries that initialize in this way. The problem occurs directly when liveSocket.connect() is called (https://github.com/phoenixframework/phoenix_live_view). Before this function is called, my js library initializes on the element without issue, however when this connect function is called, the element breaks, rendering it unusable.

Is there an easy solution to this that i’m missing, or is this just a side-effect of how live view works?

Thanks

You need a way to initialize those libraries again if the DOM of elements changes. This is not really an issue specific to LiveView, but exists for each library, which updates DOM nodes, like for example Turbolinks or pjax.

So the only solutions are either to embed the js into the .leex template, or to create a mutationobserver to watch for changes in the live-view template?

1 Like

Those or see if you can hook into liveview’s usage of morphdom.

Ok thanks for clarifying that. Can we implement a general solution for such situations, or is it not necessary? I’d say it would be quite a common problem for people with api-generated inputs (e.g. autocomplete, selects, etc). “hooking into liveview’s morphdom usage” doesn’t sound so clean, perhaps a live view focused solution could provide a lot of value if this is a common problem?

Afaik LiveView has nothing to do with rendering of actual DOM. It fully delegates to morphdom to replace the current DOM with the markup received from the server.

We want to support a “can’t touch this” or similar annotation in future Phoenix.LiveView versions. This way, if something is changed, we won’t overwrite it.

3 Likes

Actually, it is already supported: phx-ignore=true!

7 Likes

couldn’t find it in the docs, but that’s awesome! to clarify, should the following code not update the “country_id” field in my changeset in the <em> element when i select a different value?

<em><%= inspect(@changeset) %></em>
<%= select f, :country_id, ["America": 1, "Germany": 2, "Japan": 3, "France": nil], phx_ignore: true %>

The changeset in <em> still updates the “country_id” param on :validation, and it seems like the js-enhanced element still breaks on validation

That’s what I think, yes. But make sure you also do mix deps.update phoenix_live_view.

phx-ignore did the trick jose, thank you both

*edit: sorry false alarm, apparently the input with phx_ignore is still being validated. I’ll see if i can find another solution using javascript

1 Like