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


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

	        <div class="thread-main">
	            <div class="post-body" data-turbo="false">
								<p>You can also focus an input by using a <a href="https://hexdocs.pm/phoenix_live_view/Phoenix.LiveView.html#push_event/3" rel="noopener nofollow ugc">LiveView <code>push_event</code></a> if you need the server, or via the <a href="https://hexdocs.pm/phoenix_live_view/Phoenix.LiveView.JS.html#module-enhanced-push-events" rel="noopener nofollow ugc">LiveView.JS push api</a> without the server by adding <code>JS.dispatch</code> to it. So these are just slightly different flows with slightly different use-cases from the hooks example that <a class="mention" href="/u/ibarch" rel="nofollow">@ibarch</a> posted.</p>
<h3><a name="p-246108-from-the-server-1" class="anchor" href="#p-246108-from-the-server-1" aria-label="Heading link" rel="nofollow"></a>From the Server</h3>
<p>Push a JS event from a <code>handle_event</code> or <code>handle_input</code> function. You catch your pushed event in either app.js with a <code>window.addEventListener</code> or in a LiveView hook, and then send your changes to the DOM from there.</p>
<p>So that’s something like:</p>
<ol>
<li>Start with an instigating event, for example a click.</li>
</ol>
<pre data-code-wrap="elixir"><code class="lang-elixir">&lt;span phx-click="do_stuff_plus_focus_my_input" ...&gt;Just click it&lt;/span&gt; 
</code></pre>
<ol start="2">
<li>Handle it and send a <a href="https://hexdocs.pm/phoenix_live_view/Phoenix.LiveView.html#push_event/3" rel="noopener nofollow ugc">push_event</a>. I’ve called mine <code>focusElementById</code> and sent a little map with the id of the input I want to focus. That map becomes the value for the JavaScript event object’s <code>detail</code> key, as you’ll see in the third step.</li>
</ol>
<pre data-code-wrap="elixir"><code class="lang-elixir"> def handle_event("do_stuff_plus_focus_my_input", %{"foo" =&gt; bar}, socket) do
    socket = assign(socket, foo: bar)
    {:noreply, push_event(socket, "focusElementById", %{id: "my-input"})}
 end
</code></pre>
<ol start="3">
<li>Now catch that pushed event either from a hook or, as here, from <code>app.js</code>. The id we included (“my-input”) is in the event object as <code>event.detail.id</code>. Then just use standard JS’ <code>.focus()</code> and you’re done.</li>
</ol>
<pre data-code-wrap="elixir"><code class="lang-elixir"># app.js 
window.addEventListener(`phx:focusElementById`, (event) =&gt; {
  document.getElementById(event.detail.id).focus() 
})
</code></pre>
<p>Anyway the  <a href="https://hexdocs.pm/phoenix_live_view/Phoenix.LiveView.html#push_event/3" rel="noopener nofollow ugc"><code>push_event</code></a> docs go over all of this and are probably better written than what I have here.</p>
<h3><a name="p-246108-client-only-version-2" class="anchor" href="#p-246108-client-only-version-2" aria-label="Heading link" rel="nofollow"></a>Client-only Version</h3>
<p>I’ve also finally noticed that <code>LiveView.JS</code> has a function called <a href="https://hexdocs.pm/phoenix_live_view/Phoenix.LiveView.JS.html#module-enhanced-push-events" rel="noopener nofollow ugc">push</a> that lets you compose events that you send from templates. We can use that with JS.dispatch to cut out the server.</p>
<ol>
<li><code>JS.push</code> and <code>JS.dispatch</code> in action.</li>
</ol>
<pre data-code-wrap="elixir"><code class="lang-elixir"># plz excuse the formatting...
&lt;span phx-click={ JS.push("choose_part_of_speech") 
                  |&gt; JS.dispatch("phx:focusMe", to: "#my-input") 
                }&gt;Click it good&lt;/span&gt;

</code></pre>
<ol start="2">
<li>We can grab that event with a <code>window.addEventListener</code>. This is almost the same as with the server, but we’re sending the id name as a string and not in a map, so our JavaScript event object in our listener now has our element ID under <code>target</code> and not <code>detail</code> in a map. So we access the id with <code>event.target.id</code>. Just small differences that keep me in the docs and that I hope will be automated away…  You’ll see below.</li>
</ol>
<pre data-code-wrap="elixir"><code class="lang-elixir"># app.js
window.addEventListener(`phx:focusMe`, (event) =&gt; {
  document.getElementById(event.target.id).focus()
})

</code></pre>
<p>And that’s it. It’s all in the docs, but writing things out makes it easier for me to remember.</p> 
	            </div>

	            <div class="base-line">
	                <div class="thread-counters">
	                    <span class="thread-count count-likes js-likers-trigger" title="Likes" data-post-id="246108" data-batch-url="/posts/batch_likers">
                        7
                      </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/phoenix-liveview-callbacks-to-put-text-input-focus-on-the-selected-input-field/21148/12">Post #11</a>
	                </div>
	            </div>
              <div id="likers-container-246108" 
                   class="likers-container"
                   data-first-post="false"
                   data-batch-url="/posts/batch_likers">
                   <div class="likers-placeholder" 
                     data-likers-post-id="246108"
                     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="270493" data-post-id="270493">
  <section>
    <div class="post-wrap">


					<div class="post-header">
		        <div class="user-avatar">
		          <img alt="ChrisB" src="/assets/icons/user-9f439610.png" width="120" height="120" />
		        </div>
					
						<div class="user-details">
		          <div class="user-name">
		            <h3>
                  ChrisB
                  </h3>
		          </div>
						
						</div>
					
					</div>

	        <div class="thread-main">
	            <div class="post-body" data-turbo="false">
								<p>This post was so helpful that I decided to register on the forum and add to the thread.</p>
<p>In the Client-only Version, it seems like you don’t need the</p>
<blockquote>
<p>JS.push(“choose_part_of_speech”)</p>
</blockquote>
<p>that line actually [unnecessary] pushes the event to the server.</p>
<p>Simple</p>
<blockquote>
<p>JS.dispatch(“phx:focusMe”, to: “<span class="hashtag-raw">#my-input</span>”)</p>
</blockquote>
<p>seems like is enough to do the trick. I didn’t try it in the code yet. This is based on the docs: <a href="https://hexdocs.pm/phoenix_live_view/Phoenix.LiveView.JS.html#module-custom-js-events-with-js-dispatch-1-and-window-addeventlistener" rel="noopener nofollow ugc">JS.dispatch</a></p> 
	            </div>

	            <div class="base-line">
	                <div class="thread-counters">
	                    <span class="thread-count count-likes js-likers-trigger" title="Likes" data-post-id="270493" 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/phoenix-liveview-callbacks-to-put-text-input-focus-on-the-selected-input-field/21148/13">Post #12</a>
	                </div>
	            </div>
              <div id="likers-container-270493" 
                   class="likers-container"
                   data-first-post="false"
                   data-batch-url="/posts/batch_likers">
                   <div class="likers-placeholder" 
                     data-likers-post-id="270493"
                     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 #12"></div>
  </section>
</div>
    <div class="postbit" id="270627" data-post-id="270627">
  <section>
    <div class="post-wrap">


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

	        <div class="thread-main">
	            <div class="post-body" data-turbo="false">
								<p>There’s also <a href="https://hexdocs.pm/phoenix_live_view/Phoenix.LiveView.JS.html#focus/0" rel="noopener nofollow ugc">JS.focus</a> now.</p> 
	            </div>

	            <div class="base-line">
	                <div class="thread-counters">
	                    <span class="thread-count count-likes js-likers-trigger" title="Likes" data-post-id="270627" data-batch-url="/posts/batch_likers">
                        4
                      </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/phoenix-liveview-callbacks-to-put-text-input-focus-on-the-selected-input-field/21148/14">Post #13</a>
	                </div>
	            </div>
              <div id="likers-container-270627" 
                   class="likers-container"
                   data-first-post="false"
                   data-batch-url="/posts/batch_likers">
                   <div class="likers-placeholder" 
                     data-likers-post-id="270627"
                     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="285556" data-post-id="285556">
  <section>
    <div class="post-wrap">


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

	        <div class="thread-main">
	            <div class="post-body" data-turbo="false">
								<p>And does anyone know how to use it? I just added it like an attribute, but navigating between live_views did not set the focus. has this somehow to be activated?</p> 
	            </div>

	            <div class="base-line">
	                <div class="thread-counters">
	                    <span class="thread-count count-likes js-likers-trigger" title="Likes" data-post-id="285556" 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/phoenix-liveview-callbacks-to-put-text-input-focus-on-the-selected-input-field/21148/15">Post #14</a>
	                </div>
	            </div>
              <div id="likers-container-285556" 
                   class="likers-container"
                   data-first-post="false"
                   data-batch-url="/posts/batch_likers">
                   <div class="likers-placeholder" 
                     data-likers-post-id="285556"
                     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="321220" data-post-id="321220">
  <section>
    <div class="post-wrap">


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

	        <div class="thread-main">
	            <div class="post-body" data-turbo="false">
								<p>For anyone else finding this, I have a case where when a user navigates to my live view I want a specific input field to have the focus immediately (i.e. a search form).<br>
Using the <a href="https://hexdocs.pm/phoenix_live_view/bindings.html#lifecycle-events" rel="noopener nofollow ugc">lifecyle events</a> and <a href="https://hexdocs.pm/phoenix_live_view/Phoenix.LiveView.JS.html#focus/0" rel="noopener nofollow ugc">JS.focus</a>, it was as easy as:</p>
<pre data-code-wrap="elixir"><code class="lang-elixir">&lt;.input field={@form["q"]} phx-mounted={JS.focus()} /&gt;
</code></pre> 
	            </div>

	            <div class="base-line">
	                <div class="thread-counters">
	                    <span class="thread-count count-likes js-likers-trigger" title="Likes" data-post-id="321220" data-batch-url="/posts/batch_likers">
                        4
                      </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/phoenix-liveview-callbacks-to-put-text-input-focus-on-the-selected-input-field/21148/16">Post #15</a>
	                </div>
	            </div>
              <div id="likers-container-321220" 
                   class="likers-container"
                   data-first-post="false"
                   data-batch-url="/posts/batch_likers">
                   <div class="likers-placeholder" 
                     data-likers-post-id="321220"
                     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="347319" data-post-id="347319">
  <section>
    <div class="post-wrap">


					<div class="post-header">
		        <div class="user-avatar">
		          <img alt="jameskent" src="/assets/icons/user-9f439610.png" width="120" height="120" />
		        </div>
					
						<div class="user-details">
		          <div class="user-name">
		            <h3>
                  jameskent
                  </h3>
		          </div>
						
						</div>
					
					</div>

	        <div class="thread-main">
	            <div class="post-body" data-turbo="false">
								<p>I spend many hours trying to solve “focus problem”. And I’ve found a solution, which works with all three browsers I tested. Is working all the time, not once.<br>
I used <code>phx-hook</code>, <code>update</code> function in <code>hooks.js</code>, where I put: <code>document.getElementById("input_user_response").focus({ focusVisible: true })</code></p>
<p><code>phx-hook</code> was attached to <code>div</code> and I wanted to set focus on textarea input outside of that div.<br>
And my solution is working great, I don’t know why exactly. I suspect my solution is working because in that div where <code>phx-hook</code> is attached, is liveview component which visibility change after user click some button. So hook is run in the right time.</p>
<p>Focus is complicated: <a href="https://developer.mozilla.org/en-US/docs/Web/CSS/:focus-visible" class="inline-onebox" rel="noopener nofollow ugc">:focus-visible CSS pseudo-class - CSS | MDN</a></p> 
	            </div>

	            <div class="base-line">
	                <div class="thread-counters">
	                    <span class="thread-count count-likes js-likers-trigger" title="Likes" data-post-id="347319" 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/phoenix-liveview-callbacks-to-put-text-input-focus-on-the-selected-input-field/21148/17">Post #16</a>
	                </div>
	            </div>
              <div id="likers-container-347319" 
                   class="likers-container"
                   data-first-post="false"
                   data-batch-url="/posts/batch_likers">
                   <div class="likers-placeholder" 
                     data-likers-post-id="347319"
                     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>