Earlborn

Earlborn

What's the difference between Phoenix and LiveView?

Could someone please explain the difference between phoenix and liveview? Is liveview necessary for ANY dynamic content?

Without liveview, could i build a counter with increment and decrement functions that updates its state dynamically on the front end?

Im just beginning to learn phoenix, and was just curious how far phoenix could take me without liveview; for no real reason. Thanks in advance!

First Post!

7stud

7stud

You can build a counter on a web page with simple javascript that never contacts the server, so you don’t need LiveView. Save the following html/javascript in a file and load it in your browser:

<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Counter</title>
</head>

<body>
    <div id="counter">0</div>
    <button id="incr">Increment</button>
    <button id="decr">Decrement</button>

    <script>
        "use strict"
    
        function incr(event) {
            let div = document.querySelector("#counter") 
            let current_val = Number(div.innerHTML)
            div.innerHTML = current_val + 1
        }
        function decr(event) {
            let div = document.querySelector("#counter") 
            let current_val = Number(div.innerHTML)
            div.innerHTML =  current_val - 1
        }
    
        document.querySelector("#incr").addEventListener("click", incr)
        document.querySelector("#decr").addEventListener("click", decr)
       
    </script>
</body>
</html>

And, with a little more work, you can write javascript that contacts the server, then updates the web page with data returned by the server.

What LiveView does is it lets you execute a lot of very complex javascript, where the web page is instantaneously updating the server with its state, and the server is instantaneously updating the contents of the web page-without knowing or writing any javascript.

Most Liked

adw632

adw632

Liveview is a part of Phoenix (obviously) and cannot work without Phoenix framework. Phoenix can be used for serving Liveviews, dead views and APIs.

Dead views cannot interact with Phoenix except to send another request for another page or submit a form unless using Phoenix channels.

Phoenix channels opened up the possibility of sending events to clients over websocket and those pages may be served by controllers serving dead views. This requires client side javascript for interactivity (which is served as part of your dead view page). Outside of Phoenix channels Phoenix will not have any interaction with the client until the client sends another HTTP request (traditional web).

Liveview uses a similar approach to Phoenix channels by using a web socket from the client to the Phoenix server to communicate over. In the case of LiveView the client interracts with a LiveView Elixir process that maintains state on the server for that client. The client can then interact with the server process over that socket, to send events, forms etc and receive an updated view in a highly interactive manner. Liveview optimizes sending the refreshed view back to the client by only sending the data that changed as the html is mostly static and doesn’t need to be sent more than once on the initial page render. This can make Liveview more efficient than most APIs for updating views.

This does mean interactivity requires a round trip and therefore latency can be an issue for certain UI interactions. Using a Phoenix JS helpers can help with this as can using Liveview hooks. However for me the real sweet spot is custom elements (web components) so you can almost write static views and get very nice interactivity encapsulated in custom elements (for example Shoelace) without having to go down a JavaScript framework path.

adw632

adw632

Here is an example of defining and using a custom element <my-counter> in regular html:

<!DOCTYPE html>
<html lang="en">
  <my-counter></my-counter>

  <script type="module">
    import { LitElement, html } from 'https://unpkg.com/@polymer/lit-element@latest/lit-element.js?module';

    class Counter extends LitElement {
      static get properties() {
        return {
          count: { type: Number },
        };
      }

      constructor() {
        super();
        this.count = 0;
      }

      setCount = count => {
        this.count = count;
      };

      render() {
        const { count } = this;
        return html`
          <h1>Lit Element - Counter</h1>
          <h2>You clicked ${count} times</h2>
          <button type="button" @click=${() => this.setCount(count - 1)}>Decrement</button>
          <button type="button" @click=${() => this.setCount(count + 1)}>Increment</button>
        `;
      }
    }

    customElements.define('my-counter', Counter);
  </script>
</html>

In my project I just put web components like above (the part within the script tag) into my assets folder, import them from assets/app.js and then use them in my app like regular html elements. It’s a nice way to get enriched UI be it dead views or live views without buying into a JS framework.

You can see the above in action here.

Where Next?

Popular in Questions Top

hariharasudhan94
I would like to know what is the best IDE for elixir development?
New
mcarvalho
What is the difference between System.get_env and Application.get_env? For example, what are best practices to use one versus another.
New
stefanchrobot
What’s the safe way to decode a JSON string into a struct? I want to avoid calling String.to_atom. Jason.decode can give me a map with st...
New
dokuzbir
I want to highlight html closing tags when i click a html tag. That works in .html files but doesnt work for html.eex templates. How can...
New
jerry
Good day to you all. I have been struggling to get a query involving like and ilike to work. Can anyone assist me on this, please? pro...
New
vrod
I am using the Starship cross-shell prompt – it seems pretty nice, but I get some errors: [WARN] - (starship::utils): Executing command ...
New
Harrisonl
We have an ECS cluster with 4 services, where each task joins a single cluster, via discovery ECS discovery service. Currently when I de...
New

Other popular topics Top

vertexbuffer
Hello, can anybody help here..? I have a list of players and I what to delete an element, but every for loop the list is reverting to ori...
New
hariharasudhan94
Lets say I have map like this fetching from my database %{"_id" =&gt; #BSON.ObjectId&lt;58eb1a7a9ad169198c3dXXXX&gt;, "email" =&gt; ...
New
saif
Hello everyone, Long time lurker first time poster here. I’ve recently begun working on Elixir full-time again! :raised_hands: It’s been...
New
JorisKok
I have a server on AWS, and was running a load test using artillery. When looking at the Phoenix dashboard I see the Ports going to 100% ...
New
Harrisonl
We have an ECS cluster with 4 services, where each task joins a single cluster, via discovery ECS discovery service. Currently when I de...
New
sergio
Kind of like when jquery came out, it was super necessary. Existing drag and drop libraries have a bunch of baggage to support old browse...
New

We're in Beta

About us Mission Statement