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


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

	        <div class="thread-main">
	            <div class="post-body" data-turbo="false">
								<p>The important thing to remember is that the <code>JS</code> commands are not executed at the time they’re invoked, they’re added to the JS struct as a sort of “batch” command – You can <a href="https://github.com/phoenixframework/phoenix_live_view/blob/v0.18.1/lib/phoenix_live_view/js.ex#L435" rel="noopener nofollow ugc">see here</a> that <code>add_class</code> doesn’t actually add the class, but puts an “op” into the <code>ops</code> field of the <code>JS</code> struct as a command</p>
<p>So, when <code>add_class</code> is invoked, even though it comes after <code>remove_class</code>, the classes haven’t actually been removed from the element. That’s why the <code>:not</code> selector works</p>
<p>So at the end of the <code>toggle_class</code> fn above, the JS struct has two <code>ops</code>, 1 for removing classes, and 1 for adding classes, with the end-result being a toggle</p> 
	            </div>

	            <div class="base-line">
	                <div class="thread-counters">
	                    <span class="thread-count count-likes js-likers-trigger" title="Likes" data-post-id="263597" 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/toggle-classes-with-phoenix-liveview-js/45608/12">Post #11</a>
	                </div>
	            </div>
              <div id="likers-container-263597" 
                   class="likers-container"
                   data-first-post="false"
                   data-batch-url="/posts/batch_likers">
                   <div class="likers-placeholder" 
                     data-likers-post-id="263597"
                     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="263599" data-post-id="263599">
  <section>
    <div class="post-wrap">


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

	        <div class="thread-main">
	            <div class="post-body" data-turbo="false">
								<aside class="quote no-group" data-username="JohnnyCurran" data-post="12" data-topic="45608">
<div class="title">
<div class="quote-controls"></div>
<img alt="" width="24" height="24" src="https://forum.elixirforum.com/user_avatar/forum.elixirforum.com/johnnycurran/48/23380_2.png" class="avatar"> JohnnyCurran:</div>
<blockquote>
<p>The important thing to remember is that the <code>JS</code> commands are not executed at the time they’re invoked, they’re added to the JS struct as a sort of “batch” command – You can <a href="https://github.com/phoenixframework/phoenix_live_view/blob/v0.18.1/lib/phoenix_live_view/js.ex#L435" rel="noopener nofollow ugc">see here</a> that <code>add_class</code> doesn’t actually add the class, but puts an “op” into the <code>ops</code> field of the <code>JS</code> struct as a command</p>
</blockquote>
</aside>
<p>I’m aware of that. But that’s only where the commands are stored in the page waiting to be executed by the javascript front end. The js front-end executes them <a href="https://github.com/phoenixframework/phoenix_live_view/blob/46202392f6f3001110dcb4b59d6c986d8698699c/assets/js/phoenix_live_view/js.js#L12" rel="noopener nofollow ugc">here</a> in sequence, so without special care the end  result would be a noop (remove the class, the add the class). Something is happening at the JS level that prevents it, not in Elixir.</p> 
	            </div>

	            <div class="base-line">
	                <div class="thread-counters">
	                    <span class="thread-count count-likes js-likers-trigger" title="Likes" data-post-id="263599" 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/toggle-classes-with-phoenix-liveview-js/45608/13">Post #12</a>
	                </div>
	            </div>
              <div id="likers-container-263599" 
                   class="likers-container"
                   data-first-post="false"
                   data-batch-url="/posts/batch_likers">
                   <div class="likers-placeholder" 
                     data-likers-post-id="263599"
                     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="263602" data-post-id="263602">
  <section>
    <div class="post-wrap">


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

	        <div class="thread-main">
	            <div class="post-body" data-turbo="false">
								<p>I see what you’re getting at.</p>
<p>So – Only thing I can think is that the class names are collected before any of the JS commands are executed.</p>
<p>I’m digging through the live_view.js to see the order of execution but haven’t gotten it 100% yet</p> 
	            </div>

	            <div class="base-line">
	                <div class="thread-counters">
	                    <span class="thread-count count-likes js-likers-trigger" title="Likes" data-post-id="263602" 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/toggle-classes-with-phoenix-liveview-js/45608/14">Post #13</a>
	                </div>
	            </div>
              <div id="likers-container-263602" 
                   class="likers-container"
                   data-first-post="false"
                   data-batch-url="/posts/batch_likers">
                   <div class="likers-placeholder" 
                     data-likers-post-id="263602"
                     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="269949" data-post-id="269949">
  <section>
    <div class="post-wrap">


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

	        <div class="thread-main">
	            <div class="post-body" data-turbo="false">
								<p>A simple way to solve this by native html:</p>
<pre data-code-wrap="html"><code class="lang-html">&lt;button 
  onclick="document.getElementById('element-ie').classList.toggle('toggle-class')"
&gt;
  click
&lt;/click&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="269949" 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/toggle-classes-with-phoenix-liveview-js/45608/15">Post #14</a>
	                </div>
	            </div>
              <div id="likers-container-269949" 
                   class="likers-container"
                   data-first-post="false"
                   data-batch-url="/posts/batch_likers">
                   <div class="likers-placeholder" 
                     data-likers-post-id="269949"
                     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="269951" data-post-id="269951">
  <section>
    <div class="post-wrap">


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

	        <div class="thread-main">
	            <div class="post-body" data-turbo="false">
								<p>That wont survive dom patching, probably.</p> 
	            </div>

	            <div class="base-line">
	                <div class="thread-counters">
	                    <span class="thread-count count-likes js-likers-trigger" title="Likes" data-post-id="269951" 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/toggle-classes-with-phoenix-liveview-js/45608/16">Post #15</a>
	                </div>
	            </div>
              <div id="likers-container-269951" 
                   class="likers-container"
                   data-first-post="false"
                   data-batch-url="/posts/batch_likers">
                   <div class="likers-placeholder" 
                     data-likers-post-id="269951"
                     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="286131" data-post-id="286131">
  <section>
    <div class="post-wrap">


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

	        <div class="thread-main">
	            <div class="post-body" data-turbo="false">
								<p>I tested this and it actually works with LV</p> 
	            </div>

	            <div class="base-line">
	                <div class="thread-counters">
	                    <span class="thread-count count-likes js-likers-trigger" title="Likes" data-post-id="286131" 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/toggle-classes-with-phoenix-liveview-js/45608/17">Post #16</a>
	                </div>
	            </div>
              <div id="likers-container-286131" 
                   class="likers-container"
                   data-first-post="false"
                   data-batch-url="/posts/batch_likers">
                   <div class="likers-placeholder" 
                     data-likers-post-id="286131"
                     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="286134" data-post-id="286134">
  <section>
    <div class="post-wrap">


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

	        <div class="thread-main">
	            <div class="post-body" data-turbo="false">
								<p>P.S. provided you use the phx-update=“ignore” attribute.</p> 
	            </div>

	            <div class="base-line">
	                <div class="thread-counters">
	                    <span class="thread-count count-likes js-likers-trigger" title="Likes" data-post-id="286134" 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/toggle-classes-with-phoenix-liveview-js/45608/18">Post #17</a>
	                </div>
	            </div>
              <div id="likers-container-286134" 
                   class="likers-container"
                   data-first-post="false"
                   data-batch-url="/posts/batch_likers">
                   <div class="likers-placeholder" 
                     data-likers-post-id="286134"
                     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="306918" data-post-id="306918">
  <section>
    <div class="post-wrap">


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

	        <div class="thread-main">
	            <div class="post-body" data-turbo="false">
								<p>Gonna bump this as I’m running into this again.  It’s easy to work around but it seems a bit odd that we can’t <code>toggle_class</code>.</p>
<p>With Tailwind being the out-of-the-box CSS solution, it essentially makes <code>toggle</code>, <code>show</code>, and <code>hide</code> useless since these set <code>style="display: block"</code>.  You can control the display type used on show (<code>block</code>, <code>inline-block</code>, <code>flex</code>, <code>grid</code>, …) but that doesn’t help when doing responsive design.</p>
<p>For example, I have a nav where the items are next to each other on desktop, but are stacked in the mobile burger menu.</p>
<pre data-code-wrap="elixir"><code class="lang-elixir">&lt;ul class="hidden md:flex"&gt;
  ...
&lt;/ul&gt;
</code></pre>
<p>I were to go to mobile menu and show then hide the menu, then resize into a desktop view, the menu will remain hidden because it now has <code>style="display: none"</code> on it.  I realize this is edge-casey but of course, this is exactly what clients do when they are demoing the app you’ve given them.  It’s also not <em>that</em> edge-casey at all.  For example, when working my laptop, I’ll have hexdocs open half-screen with the menu hidden.  Then when I want to dig into something and explore, I’ll full-screen hexdocs and open the menu again.  This isn’t a problem with hexdocs since its menu stays the same in both views, but that’s not always the case.</p>
<p>Of course there is an easy way around this with hooks, using different buttons for show and hide, or any of the clever ways above, but <code>toggle_class</code> would be useful in many different scenarios.  Also, JS commands just feel so good!</p> 
	            </div>

	            <div class="base-line">
	                <div class="thread-counters">
	                    <span class="thread-count count-likes js-likers-trigger" title="Likes" data-post-id="306918" data-batch-url="/posts/batch_likers">
                        3
                      </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/toggle-classes-with-phoenix-liveview-js/45608/19">Post #18</a>
	                </div>
	            </div>
              <div id="likers-container-306918" 
                   class="likers-container"
                   data-first-post="false"
                   data-batch-url="/posts/batch_likers">
                   <div class="likers-placeholder" 
                     data-likers-post-id="306918"
                     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 #18"></div>
  </section>
</div>
    <div class="postbit" id="312001" data-post-id="312001">
  <section>
    <div class="post-wrap">


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

	        <div class="thread-main">
	            <div class="post-body" data-turbo="false">
								<aside class="quote no-group" data-username="Dabsy" data-post="2" data-topic="45608">
<div class="title">
<div class="quote-controls"></div>
<img alt="" width="24" height="24" src="https://forum.elixirforum.com/user_avatar/forum.elixirforum.com/dabsy/48/34413_2.png" class="avatar"> Dabsy:</div>
<blockquote>
<p>I came here to ask this just now trying to make an indicator transform 180 degrees and <em>not</em> disappear.</p>
</blockquote>
</aside>
<p>Here’s the approach that works for me. It rotates a chevron icon by 180 degrees and then back on the next tap.</p>
<p>First in the template:</p>
<pre data-code-wrap="elixir"><code class="lang-elixir">&lt;div
  id="dropdown-icon"
  phx-click="toggle-dropdown" 
  class={[
    "p-4 transition-transform ease-linear duration-200",
    (@show_dropdown? &amp;&amp; "rotate-180") || "rotate-0"
  ]}
&gt;
  &lt;.icon name="hero-chevron-down-mini" class="h-5 w-5" /&gt;
&lt;/div&gt;
</code></pre>
<p>Then, in the liveview:</p>
<pre data-code-wrap="elixir"><code class="lang-elixir">  def handle_event("toggle-dropdown", _params, socket) do
    {:noreply, update(socket, :show_dropdown?, fn val -&gt; not val end)}
  end
</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="312001" 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/toggle-classes-with-phoenix-liveview-js/45608/20">Post #19</a>
	                </div>
	            </div>
              <div id="likers-container-312001" 
                   class="likers-container"
                   data-first-post="false"
                   data-batch-url="/posts/batch_likers">
                   <div class="likers-placeholder" 
                     data-likers-post-id="312001"
                     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 #19"></div>
  </section>
</div>
    <div class="postbit" id="316136" data-post-id="316136">
  <section>
    <div class="post-wrap">


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

	        <div class="thread-main">
	            <div class="post-body" data-turbo="false">
								<p>I came here to find a solution for toggling classes.  Just checked the <a href="https://github.com/phoenixframework/phoenix_live_view/pull/1721" rel="noopener nofollow ugc">PR</a>.  It has been merged and will be available in v0.20.4!</p>
<aside class="onebox githubblob" data-onebox-src="https://github.com/phoenixframework/phoenix_live_view/blob/main/CHANGELOG.md#0204">
  <header class="source">

      <a href="https://github.com/phoenixframework/phoenix_live_view/blob/main/CHANGELOG.md#0204" target="_blank" rel="noopener nofollow ugc">github.com/phoenixframework/phoenix_live_view</a>
  </header>

  <article class="onebox-body">
    <h4><a href="https://github.com/phoenixframework/phoenix_live_view/blob/main/CHANGELOG.md#0204" target="_blank" rel="noopener nofollow ugc">CHANGELOG.md</a></h4>

<div class="git-blob-info">
  <a href="https://github.com/phoenixframework/phoenix_live_view/blob/main/CHANGELOG.md#0204" rel="noopener nofollow ugc"><code>main</code></a>
</div>


      <pre><code class="lang-md"># Changelog for v1.2

## Colocated CSS

LiveView v1.2 introduces colocated CSS to allow writing CSS rules in the same file as your regular component code.

To use colocated CSS, you need to implement the `Phoenix.LiveView.ColocatedCSS` behaviour. See the module documentation for more details.
It also includes instructions for configuring `:tailwind` to bundle colocated CSS.

Then, you can define it similar to how you would define a colocated hook or `Phoenix.LiveView.ColocatedJS`:

```elixir
def table(assigns) do
  ~H"""
  &lt;style :type={MyAppWeb.ColocatedCSS}&gt;
    thead color: {
      ...;
    }
    tbody, tr:hover {
      ...
</code></pre>



  This file has been truncated. <a href="https://github.com/phoenixframework/phoenix_live_view/blob/main/CHANGELOG.md#0204" target="_blank" rel="noopener nofollow ugc">show original</a>

  </article>

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

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

	            <div class="base-line">
	                <div class="thread-counters">
	                    <span class="thread-count count-likes js-likers-trigger" title="Likes" data-post-id="316136" 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/toggle-classes-with-phoenix-liveview-js/45608/21">Post #20</a>
	                </div>
	            </div>
              <div id="likers-container-316136" 
                   class="likers-container"
                   data-first-post="false"
                   data-batch-url="/posts/batch_likers">
                   <div class="likers-placeholder" 
                     data-likers-post-id="316136"
                     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>