Operating system: Linux workstation 5.10.2-2-MANJARO #1 SMP PREEMPT Tue Dec 22 08:14:42 UTC 2020 x86_64 GNU/Linux
Chromium: Version 87.0.4280.88 (Official Build) Arch Linux (64-bit)
Hi. So the title is kinda vague because the example that I cooked up actually shows multiple issues.
I love AlpineJS and Chris himself said here that it
plays nicely with LiveView’s own DOM patching [...]
This is what mix phx.new with --live argument creates, with the following changes:
The database password in config/dev.exs has been changed to dev to work in my environment. You might want to change it back when cloning.
Alpine ^2.8.0 has been added to assets/packages.json.
assets/js/app.js has been updated to include the liveSocket preferences Chris mentioned in the post I linked above. This has been copy and pasted.
lib/minimal_alpine_rendering_example_web/page_live.ex and .html.leex have been changed to showcase my issue.
Alpine x-on:click ("This uses x-on:click")
Expected behavior
Our example allows us to add an item to a list of maps. In my actual application, it is a list of structs that Ecto fetches from the database, but as far as I know structs are just maps under the hood and our example with a normal map works just the same.
With the two elements initially added to the list in mount/3, both buttons "Alert with element" open an alert with the correct corresponding list item. The button for Element 1 produces "1, Element 1", the button for Element 2 produces "2, Element 2".
When we add an element to the list by clicking "Add an element", Element 3 shows up. It is prepended to the list in handle_event/3 inside page_live.ex.
Now, clicking our "Alert with element" button should produce "3, Element 3" for that table row.
Actual behavior
It does not. Actually, our buttons now map as follows:
Element 1 -> alert 1, Element 1
Element 2 -> alert 1, Element 1
Element 3 -> alert 2, Element 2
Let's add a fourth element. The buttons now are:
Element 1 -> alert 1, Element 1
Element 2 -> alert 1, Element 1
Element 3 -> alert 1, Element 1
Element 4 -> alert 2, Element 2
Weirdly enough, inspecting the last button reveals <button x-data x-on:click="alert('4, Element 4')" :key="4" key="4">Alert with element</button>... just pressing it alerts with a different content.
I have not been able to figure out where the discrepancy between markup and actual JavaScript action comes from, but it does work without LiveView.
Alpine @click ("This uses @click")
Expected behavior
Alpine allows using @click as shortcut declaration for x-on:click.
Actual behavior
Using this shortcut breaks LiveView completely.
phoenix_live_view.js throws the Uncaught DOMException: Failed to execute 'setAttribute' on 'Element': '@click' is not a valid attribute name. in the console.
Interestingly, adding an element replaces the previous table row. The first one always remains, but the second is replaced by the newly added element. As such, we can never have more than two elements rendered in the table (unless we start with more than two in mount/3, in which case there will always be as many table rows rendered as the length of the initial list, with the topmost one being replaced by each new one).
Additionally, after @click, changes are not rendered at all anymore, as seen after the "This is without any alpine declarations, but after @click is used" heading.
Closing
The @click behavior is not extremely serious because it is just a shortcut, but x-on:click breaking when looping through a list actually breaks my page.
I hope my example is enough to reproduce, if there are any questions I am happy to help out.
For x-on:click I have added a workaround using x-data, with which Alpine DOM tracking does not fail anymore. That way, the first issue seems resolved and might not need further evaluation.
@click rendering is still broken and I have not found a solution.
So the HTML5 spec says the following about tag attributes:
Attribute names must consist of one or more characters other than the space characters, U+0000 NULL, U+0022 QUOTATION MARK ("), U+0027 APOSTROPHE ('), U+003E GREATER-THAN SIGN (>), U+002F SOLIDUS (/), and U+003D EQUALS SIGN (=) characters, the control characters, and any characters that are not defined by Unicode.
This, to me, means an @ should be a valid attribute.
On the other hand, elem.setAttribute('@click', 'value') fails with the error in my initial issue. Since this doesn't seem to be a Phoenix issue but a limitation of setAttribute, you guys might want to close this as out of scope.
When morphdom patches the DOM and unkeyed children are shuffled, they are destroyed and recreated. Adding an ID to the node ensures it exists across the patch. Thanks!
Environment
1.11.3
~> 1.5.7
v15.4.0
6.14.9
Linux workstation 5.10.2-2-MANJARO #1 SMP PREEMPT Tue Dec 22 08:14:42 UTC 2020 x86_64 GNU/Linux
Version 87.0.4280.88 (Official Build) Arch Linux (64-bit)
Hi. So the title is kinda vague because the example that I cooked up actually shows multiple issues. I love AlpineJS and Chris himself said here that it
I have unfortunately found the opposite to be true while exploring Phoenix. My example repo is here: https://github.com/cschmatzler/phoenix-alpine-example
This is what
mix phx.new
with--live
argument creates, with the following changes:config/dev.exs
has been changed todev
to work in my environment. You might want to change it back when cloning.^2.8.0
has been added toassets/packages.json
.assets/js/app.js
has been updated to include theliveSocket
preferences Chris mentioned in the post I linked above. This has been copy and pasted.lib/minimal_alpine_rendering_example_web/page_live.ex
and.html.leex
have been changed to showcase my issue.Alpine
x-on:click
("This uses x-on:click")Expected behavior
Our example allows us to add an item to a list of maps. In my actual application, it is a list of structs that Ecto fetches from the database, but as far as I know structs are just maps under the hood and our example with a normal map works just the same. With the two elements initially added to the list in
mount/3
, both buttons "Alert with element" open an alert with the correct corresponding list item. The button for Element 1 produces "1, Element 1", the button for Element 2 produces "2, Element 2". When we add an element to the list by clicking "Add an element", Element 3 shows up. It is prepended to the list inhandle_event/3
insidepage_live.ex
. Now, clicking our "Alert with element" button should produce "3, Element 3" for that table row.Actual behavior
It does not. Actually, our buttons now map as follows:
Let's add a fourth element. The buttons now are:
Weirdly enough, inspecting the last button reveals
<button x-data x-on:click="alert('4, Element 4')" :key="4" key="4">Alert with element</button>
... just pressing it alerts with a different content. I have not been able to figure out where the discrepancy between markup and actual JavaScript action comes from, but it does work without LiveView.Alpine
@click
("This uses @click")Expected behavior
Alpine allows using
@click
as shortcut declaration forx-on:click
.Actual behavior
Using this shortcut breaks LiveView completely.
phoenix_live_view.js
throws theUncaught DOMException: Failed to execute 'setAttribute' on 'Element': '@click' is not a valid attribute name.
in the console. Interestingly, adding an element replaces the previous table row. The first one always remains, but the second is replaced by the newly added element. As such, we can never have more than two elements rendered in the table (unless we start with more than two inmount/3
, in which case there will always be as many table rows rendered as the length of the initial list, with the topmost one being replaced by each new one).Additionally, after
@click
, changes are not rendered at all anymore, as seen after the "This is without any alpine declarations, but after@click
is used" heading.Closing
The
@click
behavior is not extremely serious because it is just a shortcut, butx-on:click
breaking when looping through a list actually breaks my page. I hope my example is enough to reproduce, if there are any questions I am happy to help out.For
x-on:click
I have added a workaround usingx-data
, with which Alpine DOM tracking does not fail anymore. That way, the first issue seems resolved and might not need further evaluation.@click
rendering is still broken and I have not found a solution.So the HTML5 spec says the following about tag attributes:
This, to me, means an
@
should be a valid attribute. On the other hand,elem.setAttribute('@click', 'value')
fails with the error in my initial issue. Since this doesn't seem to be a Phoenix issue but a limitation ofsetAttribute
, you guys might want to close this as out of scope.You need to provide an ID on the x-data containers:
When morphdom patches the DOM and unkeyed children are shuffled, they are destroyed and recreated. Adding an ID to the node ensures it exists across the patch. Thanks!