# Changelog ## 0.17.14 (2023-02-16) * Fix test errors caused by latest Phoenix HTML * Fix incorrect compiled asset build ## 0.17.13 (2023-02-16) * Fix data-phx-main lookup for latest Phoenix HTML ## 0.17.12 (2022-09-20) ### Enhancements - Add support for upcoming Phoenix 1.7 flash interface ## 0.17.11 (2022-07-11) ### Enhancements - Add `replaceTransport` to LiveSocket ### Bug fixes - Cancel debounced events from firing after a live navigation event - Fix hash anchor failing to scroll to anchor element on live navigation - Do not debounce `phx-blur` events ## 0.17.10 (2022-05-25) ### Bug fixes - [Formatter] Preserve single quote delimiter on attrs - [Formatter] Do not format inline elements surrounded by texts without whitespaces - [Formatter] Keep text and eex along when there isn't a whitespace - [Formatter] Fix intentional line breaks after eex expressions - [Formatter] Handle self close tags as inline - [Formatter] Do not format inline elements without whitespaces among them - [Formatter] Do not format when attr contenteditable is present ### Enhancements - [Formatter] Introduce special attr phx-no-format to skip formatting ## 0.17.9 (2022-04-07) ### Bug fixes - Fix sticky LiveViews failing to be patched during live navigation - Do not raise on dynamic `phx-update` value ## 0.17.8 (2022-04-06) ### Enhancements - Add HEEx formatter - Support `phx-change` on individual inputs - Dispatch `MouseEvent` on client - Add `:bubbles` option to `JS.dispatch` to control event bubbling - Expose underlying `liveSocket` instance on hooks - Enable client debug by default on localhost ### Bug fixes - Fix hook and sticky LiveView issues caused by back-to-back live redirects from mount - Fix hook destroyed callback failing to be invoked for children of phx-remove in some cases - Do not failsafe reload the page on push timeout if disconnected - Do not bubble navigation click events to regular phx-click's - No longer generate `csrf_token` for forms without action, reducing the payload during phx-change/phx-submit events ## 0.17.7 (2022-02-07) ### Enhancements - Optimize nested for comprehension diffs ### Bug fixes - Fix error when `live_redirect` links are clicked when not connected in certain cases ## 0.17.6 (2022-01-18) ### Enhancements - Add `JS.set_attribute` and `JS.remove_attribute` - Add `sticky: true` option to `live_render` to maintain a nested child on across live redirects - Dispatch `phx:show-start`, `phx:show-end`, `phx:hide-start` and `phx:hide-end` on `JS.show|hide|toggle` - Add `get_connect_info/2` that also works on disconnected render - Add `LiveSocket` constructor options for configuration failsafe behavior via new `maxReloads`, `reloadJitterMin`, `reloadJitterMax`, `failsafeJitter` options ### Bug fixes - Show form errors after submit even when no changes occur on server - Fix `phx-disable-with` failing to disable elements outside of forms - Fix phx ref tracking leaving elements in awaiting state when targeting an external LiveView - Fix diff on response failing to await for active transitions in certain cases - Fix `phx-click-away` not respecting `phx-target` - Fix "disconnect" broadcast failing to failsafe refresh the page - Fix `JS.push` with `:target` failing to send to correct component in certain cases ### Deprecations - Deprecate `Phoenix.LiveView.get_connect_info/1` in favor of `get_connect_info/2` - Deprecate `Phoenix.LiveViewTest.put_connect_info/2` in favor of calling the relevant functions in `Plug.Conn` - Deprecate returning "raw" values from upload callbacks on `Phoenix.LiveView.consume_uploaded_entry/3` and `Phoenix.LiveView.consume_uploaded_entries/3`. The callback must return either `{:ok, value}` or `{:postpone, value}`. Returning any other value will emit a warning. ## 0.17.5 (2021-11-02) ### Bug fixes - Do not trigger `phx-click-away` if element is not visible - Fix `phx-remove` failing to tear down nested live children ## 0.17.4 (2021-11-01) ### Bug fixes - Fix variable scoping issues causing various content block or duplication rendering bugs ## 0.17.3 (2021-10-28) ### Enhancements - Support 3-tuple for JS class transitions to support staged animations where a transition class is applied with a starting and ending class - Allow JS commands to be executed on DOM nodes outside of the LiveView container ### Optimization - Avoid duplicate statics inside comprehension. In previous versions, comprehensions were able to avoid duplication only in the content of their root. Now we recursively traverse all comprehension nodes and send the static only once for the whole comprehension. This should massively reduce the cost of sending comprehensions over the wire ### Bug fixes - Fix HTML engine bug causing expressions to be duplicated or not rendered correctly - Fix HTML engine bug causing slots to not be re-rendered when they should have - Fix form recovery being sent to wrong target ## 0.17.2 (2021-10-22) ### Bug fixes - Fix HTML engine bug causing attribute expressions to be incorrectly evaluated in certain cases - Fix show/hide/toggle custom display not being restored - Fix default `to` target for `JS.show|hide|dispatch` - Fix form input targeting ## 0.17.1 (2021-10-21) ### Bug fixes - Fix SVG element support for `phx` binding interactions ## 0.17.0 (2021-10-21) ### Breaking Changes #### `on_mount` changes The hook API introduced in LiveView 0.16 has been improved based on feedback. LiveView 0.17 removes the custom module-function callbacks for the `Phoenix.LiveView.on_mount/1` macro and the `:on_mount` option for `Phoenix.LiveView.Router.live_session/3` in favor of supporting a custom argument. For clarity, the module function to be invoked during the mount lifecycle stage will always be named `on_mount/4`. For example, if you had invoked `on_mount/1` like so: ```elixir on_mount MyAppWeb.MyHook on_mount {MyAppWeb.MyHook, :assign_current_user} ``` and defined your callbacks as: ```elixir # my_hook.ex def mount(_params, _session, _socket) do end def assign_current_user(_params, _session, _socket) do end ``` Change the callback to: ```elixir # my_hook.ex def on_mount(:default, _params, _session, _socket) do end def on_mount(:assign_current_user, _params, _session, _socket) do end ``` When given only a module name, the first argument to `on_mount/4` will be the atom `:default`. #### LEEx templates in stateful LiveComponents Stateful LiveComponents (where an `:id` is given) must now return HEEx templates (`~H` sigil or `.heex` extension). LEEx templates (`~L` sigil or `.leex` extension) are no longer supported. This addresses bugs and allows stateful components to be rendered more efficiently client-side. #### `phx-disconnected` class has been replaced with `phx-loading` Due to a bug in the newly released Safari 15, the previously used `.phx-disconnected` class has been replaced by a new `.phx-loading` class. The reason for the change is `phx.new` included a `.phx-disconnected` rule in the generated `app.css` which triggers the Safari bug. Renaming the class avoids applying the erroneous rule for existing applications. Folks can upgrade by simply renaming their `.phx-disconnected` rules to `.phx-loading`. #### `phx-capture-click` has been deprecated in favor of `phx-click-away` The new `phx-click-away` binding replaces `phx-capture-click` and is much more versatile because it can detect "click focus" being lost on containers. #### Removal of previously deprecated functionality Some functionality that was previously deprecated has been removed: - Implicit assigns in `live_component` do-blocks is no longer supported - Passing a `@socket` to `live_component` will now raise if possible ### Enhancements - Allow slots in function components: they are marked as `<:slot_name>` and can be rendered with `<%= render_slot @slot_name %>` - Add `JS` command for executing JavaScript utility operations on the client with an extended push API - Optimize string attributes: - If the attribute is a string interpolation, such as `
`, only the interpolation part is marked as dynamic - If the attribute can be empty, such as "class" and "style", keep the attribute name as static - Add a function component for rendering `Phoenix.LiveComponent`. Instead of `<%= live_component FormComponent, id: "form" %>`, you must now do: `<.live_component module={FormComponent} id="form" />` ### Bug fixes - Fix LiveViews with form recovery failing to properly mount following a reconnect when preceded by a live redirect - Fix stale session causing full redirect fallback when issuing a `push_redirect` from mount - Add workaround for Safari bug causing `` tags with srcset and video with autoplay to fail to render - Support EEx interpolation inside HTML comments in HEEx templates - Support HTML tags inside script tags (as in regular HTML) - Raise if using quotes in attribute names - Include the filename in error messages when it is not possible to parse interpolated attributes - Make sure the test client always sends the full URL on `live_patch`/`live_redirect`. This mirrors the behaviour of the JavaScript client - Do not reload flash from session on `live_redirect`s - Fix select drop-down flashes in Chrome when the DOM is patched during focus ### Deprecations - `<%= live_component MyModule, id: @user.id, user: @user %>` is deprecated in favor of `<.live_component module={MyModule} id={@user.id} user={@user} />`. Notice the new API requires using HEEx templates. This change allows us to further improve LiveComponent and bring new features such as slots to them. - `render_block/2` in deprecated in favor of `render_slot/2` ## 0.16.4 (2021-09-22) ### Enhancements - Improve HEEx error messages - Relax HTML tag validation to support mixed case tags - Support self closing HTML tags - Remove requirement for `handle_params` to be defined for lifecycle hooks ### Bug fixes - Fix pushes failing to include channel `join_ref` on messages ## 0.16.3 (2021-09-03) ### Bug fixes - Fix `on_mount` hooks calling view mount before redirecting when the hook issues a halt redirect. ## 0.16.2 (2021-09-03) ### Enhancements - Improve error messages on tokenization - Improve error message if `@inner_block` is missing ### Bug fixes - Fix `phx-change` form recovery event being sent to wrong component on reconnect when component order changes ## 0.16.1 (2021-08-26) ### Enhancements - Relax `phoenix_html` dependency requirement - Allow testing functional components by passing a function reference to `Phoenix.LiveViewTest.render_component/3` ### Bug fixes - Do not generate CSRF tokens for non-POST forms - Do not add compile-time dependencies on `on_mount` declarations ## 0.16.0 (2021-08-10) ### Security Considerations Upgrading from 0.15 LiveView v0.16 optimizes live redirects by supporting navigation purely over the existing WebSocket connection. This is accomplished by the new `live_session/3` feature of `Phoenix.LiveView.Router`. The [security guide](/guides/server/security-model.md) has always stressed the following: > ... As we have seen, LiveView begins its life-cycle as a regular HTTP > request. Then a stateful connection is established. Both the HTTP > request and the stateful connection receives the client data via > parameters and session. This means that any session validation must > happen both in the HTTP request (plug pipeline) and the stateful > connection (LiveView mount) ... These guidelines continue to be valid, but it is now essential that the stateful connection enforces authentication and session validation within the LiveView mount lifecycle because **a `live_redirect` from the client will not go through the plug pipeline** as a hard-refresh or initial HTTP render would. This means authentication, authorization, etc that may be done in the `Plug.Conn` pipeline must also be performed within the LiveView mount lifecycle. Live sessions allow you to support a shared security model by allowing `live_redirect`s to only be issued between routes defined under the same live session name. If a client attempts to live redirect to a different live session, it will be refused and a graceful client-side redirect will trigger a regular HTTP request to the attempted URL. See the `Phoenix.LiveView.Router.live_session/3` docs for more information and example usage. ### New HTML Engine LiveView v0.16 introduces HEEx (HTML + EEx) templates and the concept of function components via `Phoenix.Component`. The new HEEx templates validate the markup in the template while also providing smarter change tracking as well as syntax conveniences to make it easier to build composable components. A function component is any function that receives a map of assigns and returns a `~H` template: ```elixir defmodule MyComponent do use Phoenix.Component def btn(assigns) do ~H""" """ end end ``` This component can now be used as in your HEEx templates as: The introduction of HEEx and function components brings a series of deprecation warnings, some introduced in this release and others which will be added in the future. Note HEEx templates require Elixir v1.12+. ### Upgrading and deprecations The main deprecation in this release is that the `~L` sigil and the `.leex` extension are now soft-deprecated. The docs have been updated to discourage them and using them will emit warnings in future releases. We recommend using the `~H` sigil and the `.heex` extension for all future templates in your application. You should also plan to migrate the old templates accordingly using the recommendations below. Migrating from `LEEx` to `HEEx` is relatively straightforward. There are two main differences. First of all, HEEx does not allow interpolation inside tags. So instead of: ```elixir
...
``` One should use the HEEx syntax: ```elixir
...
``` The other difference is in regards to `form_for`. Some templates may do the following: ```elixir ~L""" <%= f = form_for @changeset, "#" %> <%= input f, :foo %> """ ``` However, when converted to `~H`, it is not valid HTML: there is a `` tag but its opening is hidden inside the Elixir code. On LiveView v0.16, there is a function component named `form`: ```elixir ~H""" <.form let={f} for={@changeset}> <%= input f, :foo %> """ ``` We understand migrating all templates from `~L` to `~H` can be a daunting task. Therefore we plan to support `~L` in LiveViews for a long time. However, we can't do the same for stateful LiveComponents, as some important client-side features and optimizations will depend on the `~H` sigil. Therefore **our recommendation is to replace `~L` by `~H` first in live components**, particularly stateful live components. Furthermore, stateless `live_component` (i.e. live components without an `:id`) will be deprecated in favor of the new function components. Our plan is to support them for a reasonable period of time, but you should avoid creating new ones in your application. ### Breaking Changes LiveView 0.16 removes the `:layout` and `:container` options from `Phoenix.LiveView.Routing.live/4` in favor of the `:root_layout` and `:container` options on `Phoenix.Router.live_session/3`. For instance, if you have the following in LiveView 0.15 and prior: ```elixir live "/path", MyAppWeb.PageLive, layout: {MyAppWeb.LayoutView, "custom_layout.html"} ``` Change it to: ```elixir live_session :session_name, root_layout: {MyAppWeb.LayoutView, "custom_layout.html"} do live "/path", MyAppWeb.PageLive end ``` On the client, the `phoenix_live_view` package no longer provides a default export for `LiveSocket`. If you have the following in your JavaScript entrypoint (typically located at `assets/js/app.js`): ```js import LiveSocket from "phoenix_live_view" ``` Change it to: ```js import { LiveSocket } from "phoenix_live_view" ``` Additionally on the client, the root LiveView element no longer exposes the LiveView module name, therefore the `phx-view` attribute is never set. Similarly, the `viewName` property of client hooks has been removed. Codebases calling a custom function `component/3` should rename it or specify its module to avoid a conflict, as LiveView introduces a macro with that name and it is special cased by the underlying engine. ### Enhancements - Introduce HEEx templates - Introduce `Phoenix.Component` - Introduce `Phoenix.Router.live_session/3` for optimized live redirects - Introduce `on_mount` and `attach_hook` hooks which provide a mechanism to tap into key stages of the LiveView lifecycle - Add upload methods to client-side hooks - [Helpers] Optimize `live_img_preview` rendering - [Helpers] Introduce `form` function component which wraps `Phoenix.HTML.form_for` - [LiveViewTest] Add `with_target` for scoping components directly - [LiveViewTest] Add `refute_redirected` - [LiveViewTest] Support multiple `phx-target` values to mirror JS client - [LiveViewTest] Add `follow_trigger_action` - [JavaScript Client] Add `sessionStorage` option `LiveSocket` constructor to support client storage overrides - [JavaScript Client] Do not failsafe reload the page in the background when a tab is unable to connect if the page is not visible ### Bug fixes - Make sure components are loaded on `render_component` to ensure all relevant callbacks are invoked - Fix `Phoenix.LiveViewTest.page_title` returning `nil` in some cases - Fix buttons being re-enabled when explicitly set to disabled on server - Fix live patch failing to update URL when live patch link is patched again via `handle_params` within the same callback lifecycle - Fix `phx-no-feedback` class not applied when page is live-patched - Fix `DOMException, querySelector, not a valid selector` when performing DOM lookups on non-standard IDs - Fix select dropdown flashing close/opened when assigns are updated on Chrome/macOS - Fix error with multiple `live_file_input` in one form - Fix race condition in `showError` causing null `querySelector` - Fix statics not resolving correctly across recursive diffs - Fix no function clause matching in `Phoenix.LiveView.Diff.many_to_iodata` - Fix upload input not being cleared after files are uploaded via a component - Fix channel crash when uploading during reconnect - Fix duplicate progress events being sent for large uploads ### Deprecations - Implicit assigns when passing a `do-end` block to `live_component` is deprecated - The `~L` sigil and the `.leex` extension are now soft-deprecated in favor of `~H` and `.heex` - Stateless live components (a `live_component` call without an `:id`) are deprecated in favor of the new function component feature ## 0.15.7 (2021-05-24) ### Bug fixes - Fix broken webpack build throwing missing morphdom dependency ## 0.15.6 (2021-05-24) ### Bug fixes - Fix live patch failing to update URL when live patch link is patched again from `handle_params` - Fix regression in `LiveViewTest.render_upload/3` when using channel uploads and progress callback - Fix component uploads not being cleaned up on remove - Fix `KeyError` on LiveView reconnect when an active upload was previously in progress ### Enhancements - Support function components via `component/3` - Optimize progress events to send less messages for larger file sizes - Allow session and local storage client overrides ### Deprecations - Deprecate `@socket/socket` argument on `live_component/3` call ## 0.15.5 (2021-04-20) ### Enhancements - Add `upload_errors/1` for returning top-level upload errors ### Bug fixes - Fix `consume_uploaded_entry/3` with external uploads causing inconsistent entries state - Fix `push_event` losing events when a single diff produces multiple events from different components - Fix deep merging of component tree sharing ## 0.15.4 (2021-01-26) ### Bug fixes - Fix nested `live_render`'s causing remound of child LiveView even when ID does not change - Do not attempt push hook events unless connected - Fix preflighted refs causing `auto_upload: true` to fail to submit form - Replace single upload entry when `max_entries` is 1 instead of accumulating multiple file selections - Fix `static_path` in `open_browser` failing to load stylesheets ## 0.15.3 (2021-01-02) ### Bug fixes - Fix `push_redirect` back causing timeout on the client ## 0.15.2 (2021-01-01) ### Backwards incompatible changes - Remove `beforeDestroy` from `phx-hook` callbacks ### Bug fixes - Fix form recovery failing to send input on first connection failure - Fix hooks not getting remounted after LiveView reconnect - Fix hooks `reconnected` callback being fired with no prior disconnect ## 0.15.1 (2020-12-20) ### Enhancements - Ensure all click events bubble for mobile Safari - Run `consume_uploaded_entries` in LiveView caller process ### Bug fixes - Fix hooks not getting remounted after LiveView recovery - Fix bug causing reload with jitter on timeout from previously closed channel - Fix component child nodes being lost when component patch goes from single root node to multiple child siblings - Fix `phx-capture-click` triggering on mouseup during text selection - Fix LiveView `push_event`'s not clearing up in components - Fix `