Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Document sticky liveview bug fix in v1.0.1 #3579

Open
wants to merge 3 commits into
base: main
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 3 additions & 2 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@ A backwards-compatible shim can be used to maintain `phx-feedback-for` in your e
import {Socket} from "phoenix";
import {LiveSocket} from "phoenix_live_view"
import phxFeedbackDom from "./phx_feedback_dom"

let csrfToken = document.querySelector("meta[name='csrf-token']").getAttribute("content");
let liveSocket = new LiveSocket("/live", Socket, {
params: {_csrf_token: csrfToken},
Expand Down Expand Up @@ -70,7 +70,7 @@ First, ensure that you are using the latest versions of `:phoenix_ecto` and `:ph
```diff
def input(%{field: %Phoenix.HTML.FormField{} = field} = assigns) do
+ errors = if Phoenix.Component.used_input?(field), do: field.errors, else: []

assigns
|> assign(field: nil, id: assigns.id || field.id)
- |> assign(:errors, Enum.map(field.errors, &translate_error(&1)))
Expand Down Expand Up @@ -116,6 +116,7 @@ generated user module:

### Bug fixes
* Fix live session verification causing logged errors, push_patch failures, and failed mounts when a cold deploy occurs
* Fix a bug where the `live_session`'s `on_mount` hooks would be called for sticky live views on connected mount. Now a `sticky` live view is consistently marked as `:not_mounted_at_router`

## 1.0.0 (2024-12-03) 🚀

Expand Down
4 changes: 3 additions & 1 deletion assets/js/phoenix_live_view/live_socket.js
Original file line number Diff line number Diff line change
Expand Up @@ -375,7 +375,9 @@ export default class LiveSocket {
DOM.all(document, `${PHX_VIEW_SELECTOR}:not([${PHX_PARENT_ID}])`, rootEl => {
if(!this.getRootById(rootEl.id)){
let view = this.newRootView(rootEl)
view.setHref(this.getHref())
// stickies cannot be mounted at the router and therefore should not
// get a href set on them
if(!DOM.isPhxSticky(rootEl)){ view.setHref(this.getHref()) }
view.join()
if(rootEl.hasAttribute(PHX_MAIN)){ this.main = view }
}
Expand Down
14 changes: 4 additions & 10 deletions lib/phoenix_live_view/channel.ex
Original file line number Diff line number Diff line change
Expand Up @@ -1558,21 +1558,15 @@ defmodule Phoenix.LiveView.Channel do

if Session.main?(session) do
# Ensure the session's LV module and live session name still match on connect.
# If the route has changed the LV module or has moved live sessions, the client
# will fallback to full page redirect to the current URL.
# If the route has changed the LV module or has moved live sessions (typically
# during a deployment), the client will fallback to full page redirect to the
# current URL.
case session_route(session, endpoint, url) do
%Route{view: ^view, live_session: %{name: ^session_name}} = route ->
{:ok, session, route, url}

# if we have a sticky LV, it will be considered a main with no live session
%Route{} when is_nil(session_name) ->
{:ok, session, nil, url}

# if we have a session, then it no longer matches and is unauthorized
%Route{} ->
{:error, :unauthorized}

nil ->
_ ->
{:error, :unauthorized}
end
else
Expand Down
2 changes: 1 addition & 1 deletion lib/phoenix_live_view/session.ex
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@ defmodule Phoenix.LiveView.Session do
live_session_vsn: nil,
assign_new: []

def main?(%Session{} = session), do: !is_nil(session.router) and !session.parent_pid
def main?(%Session{} = session), do: session.router != nil and session.parent_pid == nil

def authorize_root_redirect(%Session{} = session, %Route{} = route) do
%Session{live_session_name: session_name, live_session_vsn: session_vsn} = session
Expand Down
2 changes: 1 addition & 1 deletion test/e2e/support/issues/issue_3047.ex
Original file line number Diff line number Diff line change
Expand Up @@ -45,7 +45,7 @@ end
defmodule Phoenix.LiveViewTest.E2E.Issue3047.Sticky do
use Phoenix.LiveView

def mount(_params, _session, socket) do
def mount(:not_mounted_at_router, _session, socket) do
items =
Enum.map(1..10, fn x ->
%{id: x, name: "item-#{x}"}
Expand Down
2 changes: 1 addition & 1 deletion test/e2e/support/issues/issue_3496.ex
Original file line number Diff line number Diff line change
Expand Up @@ -87,7 +87,7 @@ end
defmodule Phoenix.LiveViewTest.E2E.Issue3496.StickyLive do
use Phoenix.LiveView

def mount(_params, _session, socket) do
def mount(:not_mounted_at_router, _session, socket) do
{:ok, socket, layout: false}
end

Expand Down
Loading