<turbo-stream action="append" target="posts_list"><template>    <div class="postbit" id="191273" data-post-id="191273">
  <section>
    <div class="post-wrap">


					<div class="post-header">
		        <div class="user-avatar">
		          <img alt="kuon" src="https://forum.elixirforum.com/user_avatar/forum.elixirforum.com/kuon/120/36090_2.png" width="120" height="120" />
		        </div>
					
						<div class="user-details">
		          <div class="user-name">
		            <h3>
                  kuon
                      <span class="op-star" title="Thread Starter">
                        <img alt="OP" class="op-star-icon" src="/assets/thread-icons/thread-icon-thread-starter-df91e872.png" />
                      </span>
                  </h3>
		          </div>
						
						</div>
					
					</div>

	        <div class="thread-main">
	            <div class="post-body" data-turbo="false">
								<p>I am currently trying a mixed approach where I would still use live view for rendering.</p>
<p>Basically, instead of rendering the whole table, I render only the visible part (in a live view), and I push the coordinates when scrolling.</p>
<p>It is still early stage but I think this road should work while requiring very minimal JS.</p> 
	            </div>

	            <div class="base-line">
	                <div class="thread-counters">
	                    <span class="thread-count count-likes js-likers-trigger" title="Likes" data-post-id="191273" data-batch-url="/posts/batch_likers">
                        0
                      </span>
                      <!-- <span class="thread-count js-solved-indicator" title="Marked as solution"></span> -->
	                </div>
	                <div class="go-to-post">
	                  <a title="Go to post" alt="Go to post" href="https://forum.elixirforum.com/t/performances-when-using-live-view-with-large-table/34674/12">Post #11</a>
	                </div>
	            </div>
              <div id="likers-container-191273" 
                   class="likers-container"
                   data-first-post="false"
                   data-batch-url="/posts/batch_likers">
                   <div class="likers-placeholder" 
                     data-likers-post-id="191273"
                     data-batch-url="/posts/batch_likers">
                  <div class="post-likers"></div>
                </div>
              </div>
	        </div>
			

    </div>

    <div class="triangle-top-right type-standard-post cat-standard-post" title="Post #11"></div>
  </section>
</div>
    <div class="postbit" id="191388" data-post-id="191388">
  <section>
    <div class="post-wrap">


					<div class="post-header">
		        <div class="user-avatar">
		          <img alt="kuon" src="https://forum.elixirforum.com/user_avatar/forum.elixirforum.com/kuon/120/36090_2.png" width="120" height="120" />
		        </div>
					
						<div class="user-details">
		          <div class="user-name">
		            <h3>
                  kuon
                      <span class="op-star" title="Thread Starter">
                        <img alt="OP" class="op-star-icon" src="/assets/thread-icons/thread-icon-thread-starter-df91e872.png" />
                      </span>
                  </h3>
		          </div>
						
						</div>
					
					</div>

	        <div class="thread-main">
	            <div class="post-body" data-turbo="false">
								<p>Ok, I ended up with the following solution:</p>
<ul>
<li>set a hook on the container like so:</li>
</ul>
<pre data-code-wrap="js"><code class="lang-js">
Hooks.table = {
  mounted () {
    this.resize()
    this.resizeListener = () =&gt; this.resize()
    this.scrollListener = (evt) =&gt; this.scroll(evt)
    window.addEventListener('resize', this.resizeListener)
    this.el.addEventListener('wheel', this.scrollListener)
  },
  destroyed () {
    window.removeEventListener('resize', this.resizeListener)
    this.el.removeEventListener('wheel', this.scrollListener)
    this.resizeListener = null
  },
  resize () {
    this.rect = this.el.getBoundingClientRect()
    this.pushEventTo('#table-component', 'resize', this.rect)
  },
  scroll (evt) {
    let d = evt.deltaY
    if (d === 0) {
      return
    }
    switch (evt.deltaMode) {
      case WheelEvent.DOM_DELTA_PIXEL:
        break;
      case WheelEvent.DOM_DELTA_LINE:
        d *= 16;
        break;
      case WheelEvent.DOM_DELTA_PAGE:
        d *= this.rect.height / 2;
        break;
    }
    let off = {x: 0, y: 0}
    if (evt.shiftKey) {
      off.x = d
    } else {
      off.y = d
    }
    this.pushEventTo('#table-component', 'scroll', off)
  }
}
</code></pre>
<p>have a simple handler like this:</p>
<pre data-code-wrap="elixir"><code class="lang-elixir">
  @impl true
  def handle_event("resize", %{"width" =&gt; width, "height" =&gt; height}, socket) do
    {:noreply,
     assign(socket, viewport: %{width: width, height: height})
     |&gt; do_fetch_data()}
  end

  @impl true
  def handle_event("scroll", %{"x" =&gt; x, "y" =&gt; y}, socket) do
    offset = socket.assigns.offset

    offset = %{
      x: offset.x + x,
      y: offset.y + y
    }

    {:noreply, assign(socket, offset: offset) |&gt; do_fetch_data()}
  end

</code></pre>
<p>Then in the <code>do_fetch_data</code> I clamp the offset, and I gather the data rows for the given view.</p>
<p>I then just render that “window” on my large data table.</p>
<p>This approach doesn’t provide native scrolling, but it is very fast and I can stream over my large table. The good side is very minimal javascript code (of course I would need a bit more for scrollbars, this is a proof of concept).</p>
<p>Live view is very fast at re-rendering the table on scroll events.</p> 
	            </div>

	            <div class="base-line">
	                <div class="thread-counters">
	                    <span class="thread-count count-likes js-likers-trigger" title="Likes" data-post-id="191388" data-batch-url="/posts/batch_likers">
                        2
                      </span>
                      <!-- <span class="thread-count js-solved-indicator" title="Marked as solution"></span> -->
	                </div>
	                <div class="go-to-post">
	                  <a title="Go to post" alt="Go to post" href="https://forum.elixirforum.com/t/performances-when-using-live-view-with-large-table/34674/13">Post #12</a>
	                </div>
	            </div>
              <div id="likers-container-191388" 
                   class="likers-container"
                   data-first-post="false"
                   data-batch-url="/posts/batch_likers">
                   <div class="likers-placeholder" 
                     data-likers-post-id="191388"
                     data-batch-url="/posts/batch_likers">
                  <div class="post-likers"></div>
                </div>
              </div>
	        </div>
			

    </div>

    <div class="triangle-top-right type-most-liked cat-most-liked" title="One of the top 3 liked posts in this thread!"></div>
  </section>
</div>
    <div class="postbit" id="191394" data-post-id="191394">
  <section>
    <div class="post-wrap">


					<div class="post-header">
		        <div class="user-avatar">
		          <img alt="harmon25" src="https://forum.elixirforum.com/user_avatar/forum.elixirforum.com/harmon25/120/1274_2.png" width="120" height="120" />
		        </div>
					
						<div class="user-details">
		          <div class="user-name">
		            <h3>
                  harmon25
                  </h3>
		          </div>
						
						</div>
					
					</div>

	        <div class="thread-main">
	            <div class="post-body" data-turbo="false">
								<p>I think the viewport / sliding window approach you have landed on is nice!</p>
<p>Pretty sure it’s the only graceful way to handle this without too much data on either the client, or the server…</p> 
	            </div>

	            <div class="base-line">
	                <div class="thread-counters">
	                    <span class="thread-count count-likes js-likers-trigger" title="Likes" data-post-id="191394" data-batch-url="/posts/batch_likers">
                        0
                      </span>
                      <!-- <span class="thread-count js-solved-indicator" title="Marked as solution"></span> -->
	                </div>
	                <div class="go-to-post">
	                  <a title="Go to post" alt="Go to post" href="https://forum.elixirforum.com/t/performances-when-using-live-view-with-large-table/34674/14">Post #13</a>
	                </div>
	            </div>
              <div id="likers-container-191394" 
                   class="likers-container"
                   data-first-post="false"
                   data-batch-url="/posts/batch_likers">
                   <div class="likers-placeholder" 
                     data-likers-post-id="191394"
                     data-batch-url="/posts/batch_likers">
                  <div class="post-likers"></div>
                </div>
              </div>
	        </div>
			

    </div>

    <div class="triangle-top-right type-standard-post cat-standard-post" title="Post #13"></div>
  </section>
</div>
    <div class="postbit" id="191416" data-post-id="191416">
  <section>
    <div class="post-wrap">


					<div class="post-header">
		        <div class="user-avatar">
		          <img alt="50kudos" src="https://forum.elixirforum.com/user_avatar/forum.elixirforum.com/50kudos/120/4435_2.png" width="120" height="120" />
		        </div>
					
						<div class="user-details">
		          <div class="user-name">
		            <h3>
                  50kudos
                  </h3>
		          </div>
						
						</div>
					
					</div>

	        <div class="thread-main">
	            <div class="post-body" data-turbo="false">
								<aside class="quote no-group" data-username="50kudos" data-post="9" data-topic="34674">
<div class="title">
<div class="quote-controls"></div>
<img alt="" width="24" height="24" src="https://forum.elixirforum.com/user_avatar/forum.elixirforum.com/50kudos/48/4435_2.png" class="avatar"> 50kudos:</div>
<blockquote>
<p>only render rows fit within screen viewport</p>
</blockquote>
</aside>
<p>That’s what I said earlier!</p>
<aside class="quote no-group" data-username="kuon" data-post="13" data-topic="34674">
<div class="title">
<div class="quote-controls"></div>
<img alt="" width="24" height="24" src="https://forum.elixirforum.com/user_avatar/forum.elixirforum.com/kuon/48/36090_2.png" class="avatar"> kuon:</div>
<blockquote>
<p>but it is very fast and I can stream over my large table</p>
</blockquote>
</aside>
<p>Is your app server in the same country or region? It’s nice to hear that rendering per scroll event is fast (I assume <code>do_fetch_data</code> hit database?), I’d love to adopt this in my app as well, I was afraid of latency in worst case scenario (e.g. EU ↔ NZ).</p> 
	            </div>

	            <div class="base-line">
	                <div class="thread-counters">
	                    <span class="thread-count count-likes js-likers-trigger" title="Likes" data-post-id="191416" data-batch-url="/posts/batch_likers">
                        0
                      </span>
                      <!-- <span class="thread-count js-solved-indicator" title="Marked as solution"></span> -->
	                </div>
	                <div class="go-to-post">
	                  <a title="Go to post" alt="Go to post" href="https://forum.elixirforum.com/t/performances-when-using-live-view-with-large-table/34674/15">Post #14</a>
	                </div>
	            </div>
              <div id="likers-container-191416" 
                   class="likers-container"
                   data-first-post="false"
                   data-batch-url="/posts/batch_likers">
                   <div class="likers-placeholder" 
                     data-likers-post-id="191416"
                     data-batch-url="/posts/batch_likers">
                  <div class="post-likers"></div>
                </div>
              </div>
	        </div>
			

    </div>

    <div class="triangle-top-right type-standard-post cat-standard-post" title="Post #14"></div>
  </section>
</div>
    <div class="postbit" id="191574" data-post-id="191574">
  <section>
    <div class="post-wrap">


					<div class="post-header">
		        <div class="user-avatar">
		          <img alt="kuon" src="https://forum.elixirforum.com/user_avatar/forum.elixirforum.com/kuon/120/36090_2.png" width="120" height="120" />
		        </div>
					
						<div class="user-details">
		          <div class="user-name">
		            <h3>
                  kuon
                      <span class="op-star" title="Thread Starter">
                        <img alt="OP" class="op-star-icon" src="/assets/thread-icons/thread-icon-thread-starter-df91e872.png" />
                      </span>
                  </h3>
		          </div>
						
						</div>
					
					</div>

	        <div class="thread-main">
	            <div class="post-body" data-turbo="false">
								<p>Yeah, I didn’t want to smart render only the required region because I was surprised at how good browser were at handling large table “out of the box”, but sadly it doesn’t play well with live view diffing mechanism.</p>
<p>As for latency, yeah, the server is located on the same country. I guess the only way to cope with larger latency would be to send more data to the client at once, and to scroll client side within that “larger data”.</p> 
	            </div>

	            <div class="base-line">
	                <div class="thread-counters">
	                    <span class="thread-count count-likes js-likers-trigger" title="Likes" data-post-id="191574" data-batch-url="/posts/batch_likers">
                        1
                      </span>
                      <!-- <span class="thread-count js-solved-indicator" title="Marked as solution"></span> -->
	                </div>
	                <div class="go-to-post">
	                  <a title="Go to post" alt="Go to post" href="https://forum.elixirforum.com/t/performances-when-using-live-view-with-large-table/34674/16">Post #15</a>
	                </div>
	            </div>
              <div id="likers-container-191574" 
                   class="likers-container"
                   data-first-post="false"
                   data-batch-url="/posts/batch_likers">
                   <div class="likers-placeholder" 
                     data-likers-post-id="191574"
                     data-batch-url="/posts/batch_likers">
                  <div class="post-likers"></div>
                </div>
              </div>
	        </div>
			

    </div>

    <div class="triangle-top-right type-standard-post cat-standard-post" title="Post #15"></div>
  </section>
</div>
    <div class="postbit" id="246297" data-post-id="246297">
  <section>
    <div class="post-wrap">


					<div class="post-header">
		        <div class="user-avatar">
		          <img alt="david" src="https://forum.elixirforum.com/user_avatar/forum.elixirforum.com/david/120/30628_2.png" width="120" height="120" />
		        </div>
					
						<div class="user-details">
		          <div class="user-name">
		            <h3>
                  david
                  </h3>
		          </div>
						
						</div>
					
					</div>

	        <div class="thread-main">
	            <div class="post-body" data-turbo="false">
								<p>I found this tutorial helpful for those looking to work with temporary assigns:<br>
<a href="https://newaperio.com/blog/updating-and-deleting-from-temporary-assigns-in-phoenix-live-view" rel="noopener nofollow ugc">Updating and Deleting from Temporary Assigns in Phoenix LiveView</a>. It’s a bit older but it checks out.</p> 
	            </div>

	            <div class="base-line">
	                <div class="thread-counters">
	                    <span class="thread-count count-likes js-likers-trigger" title="Likes" data-post-id="246297" data-batch-url="/posts/batch_likers">
                        0
                      </span>
                      <!-- <span class="thread-count js-solved-indicator" title="Marked as solution"></span> -->
	                </div>
	                <div class="go-to-post">
	                  <a title="Go to post" alt="Go to post" href="https://forum.elixirforum.com/t/performances-when-using-live-view-with-large-table/34674/17">Post #16</a>
	                </div>
	            </div>
              <div id="likers-container-246297" 
                   class="likers-container"
                   data-first-post="false"
                   data-batch-url="/posts/batch_likers">
                   <div class="likers-placeholder" 
                     data-likers-post-id="246297"
                     data-batch-url="/posts/batch_likers">
                  <div class="post-likers"></div>
                </div>
              </div>
	        </div>
			

    </div>

    <div class="triangle-top-right type-standard-post cat-standard-post" title="Post #16"></div>
  </section>
</div>
    <div class="postbit" id="248474" data-post-id="248474">
  <section>
    <div class="post-wrap">


					<div class="post-header">
		        <div class="user-avatar">
		          <img alt="adkron" src="https://forum.elixirforum.com/user_avatar/forum.elixirforum.com/adkron/120/3110_2.png" width="120" height="120" />
		        </div>
					
						<div class="user-details">
		          <div class="user-name">
		            <h3>
                  adkron
                  </h3>
		          </div>
						
						</div>
					
					</div>

	        <div class="thread-main">
	            <div class="post-body" data-turbo="false">
								<p>I’m currently running into the same issue. I have a table with some data, but not a large amount. If I get over 100 rows it starts to slow down a lot. I’m looking to put 2000 rows. I would really like to have all of that on one page.</p>
<p>It is slow even on the initial rendering of the live view. Outside of updating does anyone know how to just render it quickly? It all seems to be rendering time that is killing it all.</p>
<p>Does anyone have any idea?</p> 
	            </div>

	            <div class="base-line">
	                <div class="thread-counters">
	                    <span class="thread-count count-likes js-likers-trigger" title="Likes" data-post-id="248474" data-batch-url="/posts/batch_likers">
                        0
                      </span>
                      <!-- <span class="thread-count js-solved-indicator" title="Marked as solution"></span> -->
	                </div>
	                <div class="go-to-post">
	                  <a title="Go to post" alt="Go to post" href="https://forum.elixirforum.com/t/performances-when-using-live-view-with-large-table/34674/18">Post #17</a>
	                </div>
	            </div>
              <div id="likers-container-248474" 
                   class="likers-container"
                   data-first-post="false"
                   data-batch-url="/posts/batch_likers">
                   <div class="likers-placeholder" 
                     data-likers-post-id="248474"
                     data-batch-url="/posts/batch_likers">
                  <div class="post-likers"></div>
                </div>
              </div>
	        </div>
			

    </div>

    <div class="triangle-top-right type-standard-post cat-standard-post" title="Post #17"></div>
  </section>
</div>
    <div class="postbit" id="248475" data-post-id="248475">
  <section>
    <div class="post-wrap">


					<div class="post-header">
		        <div class="user-avatar">
		          <img alt="adkron" src="https://forum.elixirforum.com/user_avatar/forum.elixirforum.com/adkron/120/3110_2.png" width="120" height="120" />
		        </div>
					
						<div class="user-details">
		          <div class="user-name">
		            <h3>
                  adkron
                  </h3>
		          </div>
						
						</div>
					
					</div>

	        <div class="thread-main">
	            <div class="post-body" data-turbo="false">
								<p>Oh, I just learned about profiling with live view.</p>
<aside class="onebox allowlistedgeneric" data-onebox-src="https://til.hashrocket.com/posts/hsex4bgyvh-phoenix-live-view-enable-profiling">
  <header class="source">

      <a href="https://til.hashrocket.com/posts/hsex4bgyvh-phoenix-live-view-enable-profiling" target="_blank" rel="noopener nofollow ugc">til.hashrocket.com</a>
  </header>

  <article class="onebox-body">
    <div class="aspect-image" style="--aspect-ratio:560/282;"><img src="https://dys2hbvla0n8j.cloudfront.net/images/elixir_twitter_card.png" class="thumbnail" alt="" width="560" height="282"></div>

<h3><a href="https://til.hashrocket.com/posts/hsex4bgyvh-phoenix-live-view-enable-profiling" target="_blank" rel="noopener nofollow ugc">Today I Learned</a></h3>

  <p>TIL is an open-source project by Hashrocket that exists to catalogue the sharing &amp; accumulation of knowledge as it happens day-to-day.</p>


  </article>

  <div class="onebox-metadata">
    
    
  </div>

  <div style="clear: both"></div>
</aside>

<p>This might help me find it.</p> 
	            </div>

	            <div class="base-line">
	                <div class="thread-counters">
	                    <span class="thread-count count-likes js-likers-trigger" title="Likes" data-post-id="248475" data-batch-url="/posts/batch_likers">
                        2
                      </span>
                      <!-- <span class="thread-count js-solved-indicator" title="Marked as solution"></span> -->
	                </div>
	                <div class="go-to-post">
	                  <a title="Go to post" alt="Go to post" href="https://forum.elixirforum.com/t/performances-when-using-live-view-with-large-table/34674/19">Post #18</a>
	                </div>
	            </div>
              <div id="likers-container-248475" 
                   class="likers-container"
                   data-first-post="false"
                   data-batch-url="/posts/batch_likers">
                   <div class="likers-placeholder" 
                     data-likers-post-id="248475"
                     data-batch-url="/posts/batch_likers">
                  <div class="post-likers"></div>
                </div>
              </div>
	        </div>
			

    </div>

    <div class="triangle-top-right type-last-post cat-last-post" title="Last post!"></div>
  </section>
</div>
</template></turbo-stream><turbo-stream action="replace" target="load-more-container"><template><div id="load-more-container" class="load-more-container">
    <span class="all-loaded">— All posts loaded —</span>
</div></template></turbo-stream>