Navigate from JS (front) without reloading the page?


I use LiveView and Svelte. In the Svelte components, I need to navigate but I don’t found a solution without reloading the page (like <a href does).

How to navigate from the frontend (in JS) without reloading the page, as the <.link navigate="/users/settings>Test</.link> component does?

Have you come across @woutdp’s LiveSvelte?

It supports LiveView Live Navigation Events from inside Svelte components.

Yes I tried.
I mentioned Svelte but I’m looking for the way to do it in JS.

Can you please be more specific? You don’t give much information. Please provide steps so one could reproduce your issue.

There’s JS.navigate/1 and JS.patch/1 from LiveView’s client side utility commands.


Nothing specific, no issue to reproduce. It’s just that I can’t find the function or the way to change the page (liveview) without reloading all.

A link on a HEEX template with <.link navigate="/users/settings>Test</.link> component change the page (liveview) without reloading all the DOM (disconnect/reconnect the socket, reload assets, etc).

I couldn’t find anything in the docs (JS interop etc) or on the internet.

I tried randomly:

  • liveSocket.pushHistoryPatch(path, "push")
  • liveSocket.pushHistoryPatch(path, "push")
  • liveSocket.historyRedirect(path, "patch")
  • liveSocket.historyRedirect(path, "patch")

It reloads the page as a new HTTP request

1 Like

Thanks, I tried also importing it but unless I’m mistaken, it’s not exposed by phoenix_live_view.

import {JS} from 'phoenix_live_view';
import JS from 'phoenix_live_view/js';
// ...

Without success. What I’m wrong?

It seems like you want <.link patch={~p"/pages/#{@page + 1}"}>Next</.link> rather than <.link navigate={...}>.

The “patch” operations must be used when you want to navigate to the current LiveView, simply updating the URL and the current parameters, without mounting a new LiveView. When patch is used, the handle_params/3 callback is invoked and the minimal set of changes are sent to the client. See the next section for more information.

The “navigate” operations must be used when you want to dismount the current LiveView and mount a new one. You can only “navigate” between LiveViews in the same session. While redirecting, a phx-loading class is added to the LiveView, which can be used to indicate to the user a new page is being loaded.

If you attempt to patch to another LiveView or navigate across live sessions, a full page reload is triggered. This means your application continues to work, in case your application structure changes and that’s not reflected in the navigation.

Here is a quick breakdown:

  • <.link href={...}> and redirect/2 are HTTP-based, work everywhere, and perform full page reloads
  • <.link navigate={...}> and push_navigate/2 work across LiveViews in the same session. They mount a new LiveView while keeping the current layout
  • <.link patch={...}> and push_patch/2 updates the current LiveView and sends only the minimal diff while also maintaining the scroll position

source: Live navigation — Phoenix LiveView v0.19.5

1 Like

The 2 do not necessarily reload the whole page if it is in the same live_session, right?

It’s mainly to avoid disconnecting / reconnecting the socket for nothing, losing the JS state on the front side.

In short, I want with Javascript on the front end (client side), not back end. Example in assets/app.js :

// app.js
setTimeout(() -> {
// TODO: load (push or patch) current liveview to "/users/settings"
// Example: push_patch('/users/settings'); 
}, 1000)

That’s all :slight_smile:

1 Like

I’m curious as well:

  1. There’s patch for a tags,
  2. There’s push_patch to influence the page change from server side.
  3. There are JS commands: JS.patch(“/my-path”) & JS.navigate(“/my-path”)

  1. What’s the client only solution? Is it even possible? :thinking:
1 Like

Here’s an approach that works:


<div id="auto-redirect" phx-hook="AutoRedirect">
  Auto Redirecting in 3, 2, 1


const AutoRedirect = {
  mounted() {
    setTimeout(() => {
    }, 3000);

export default AutoRedirect;


defp handle_event("navigate", route, socket) do
     |> push_navigate(to: route)}

You can handle event on each live view, or use on_mount, together with live_session.


defmodule DerpyToolsWeb.Nav do
  import Phoenix.LiveView
  use Phoenix.Component

  def on_mount(:default, _params, _session, socket) do
     |> attach_hook(:auto_redirect, :handle_event, &handle_event/3)
     |> attach_hook(:inspect_source, :handle_event, &handle_event/3)

  defp handle_event("navigate", route, socket) do
     |> push_navigate(to: route)}


scope "/", DerpyToolsWeb do
  pipe_through :browser
  live_session :no_log_in_required,
    on_mount: [
      {DerpyToolsWeb.Permit, :anyone}
    ] do
    live "/", HomePageLive

    live "/blog/:post_slug", BlogLive
1 Like

Oh nice, thank you very much! Very helpful!

1 Like

Just to supplement.
pushEvent will send the event to the current liveview.
In my case my hook (auto-redirect) is a LiveComponent and although I send the pushEvent with the object of the hook, it sends it with the liveview of the current page.
Solution: pushEventTo(autoRedirectElement, ....)

1 Like

… (nothing)