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


					<div class="post-header">
		        <div class="user-avatar">
		          <img alt="bartblast" src="https://forum.elixirforum.com/user_avatar/forum.elixirforum.com/bartblast/120/17647_2.png" width="120" height="120" />
		        </div>
					
						<div class="user-details">
		          <div class="user-name">
		            <h3>
                  bartblast
                    <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 class="user-title">
									<span>Creator of Hologram</span>
			          </div>
						</div>
					
					</div>

	        <div class="thread-main">
	            <div class="post-body" data-turbo="false">
								<aside class="quote no-group" data-username="jam" data-post="27" data-topic="72518">
<div class="title">
<div class="quote-controls"></div>
<img alt="" width="24" height="24" src="https://forum.elixirforum.com/user_avatar/forum.elixirforum.com/jam/48/36266_2.png" class="avatar"> jam:</div>
<blockquote>
<p>I wonder if there is another way to cut down on boilerplate / binding maintenance with macro magic or other. Would something like this be possible?</p>
<pre data-code-wrap="elixir"><code class="lang-elixir">js do
  """
   function greet(name) { 
    return `Hello, ${name}!`;
  }
  """
end
</code></pre>
<p>Invoked with:</p>
<pre data-code-wrap="elixir"><code class="lang-elixir">JS.greet("Bart")
</code></pre>
</blockquote>
</aside>
<p>Something like this would require parsing the JS code to extract function signatures - we’d need to somehow detect that there’s a greet function with one parameter defined inside the sigil and automatically generate the corresponding Elixir bindings. Not sure it’s worth the hassle…<br>
It might make sense for non-function code fragments, but then you’re mixing JS and Elixir code in ways that could get confusing - especially for debugging and tooling support.</p>
<aside class="quote no-group" data-username="jam" data-post="27" data-topic="72518">
<div class="title">
<div class="quote-controls"></div>
<img alt="" width="24" height="24" src="https://forum.elixirforum.com/user_avatar/forum.elixirforum.com/jam/48/36266_2.png" class="avatar"> jam:</div>
<blockquote>
<p>Hmm my first reaction to this is it feels a bit complicated but maybe I’m missing something. It’s not immediate clear to me where the DX win is but it would require learning more syntax that is unique to Hologram. Since JS interop is meant to be an escape hatch, I think the js code should just be js.</p>
</blockquote>
</aside>
<p>This approach would be for power-users building interop libraries. Most developers could just use exported JS functions through FFI or event listeners and call them from Hologram.</p>
<aside class="quote no-group quote-modified" data-username="jam" data-post="27" data-topic="72518">
<div class="title">
<div class="quote-controls"></div>
<img alt="" width="24" height="24" src="https://forum.elixirforum.com/user_avatar/forum.elixirforum.com/jam/48/36266_2.png" class="avatar"> jam:</div>
<blockquote>
<aside class="quote no-group" data-username="bartblast" data-post="25" data-topic="72518">
<div class="title">
<div class="quote-controls"></div>
<img alt="" width="24" height="24" src="https://forum.elixirforum.com/user_avatar/forum.elixirforum.com/bartblast/48/17647_2.png" class="avatar"> bartblast:</div>
<blockquote>
<p><code>Hologram.dispatchAction("MyComponent", "my_action", "my_target", params)</code></p>
</blockquote>
</aside>
<p>Interesting. What do you think of using <code>Hologram.put_action</code> so there’s less surface area to learn?</p>
</blockquote>
</aside>
<p>I’m not sure about using <code>Hologram.put_action</code> since <code>put_action/3</code> in components/pages does something a little different - it modifies the struct in place and has a different set of parameters. It might be confusing to reuse the same name for what’s essentially a different operation (dispatching from JS vs modifying component struct).</p>
<aside class="quote no-group" data-username="jam" data-post="27" data-topic="72518">
<div class="title">
<div class="quote-controls"></div>
<img alt="" width="24" height="24" src="https://forum.elixirforum.com/user_avatar/forum.elixirforum.com/jam/48/36266_2.png" class="avatar"> jam:</div>
<blockquote>
<p>Also, fwiw as a minor thing, I think it’d be good to use snake_case even though it’s not the JS convention.</p>
</blockquote>
</aside>
<p>I think we should generally use JS conventions when inside JS code.</p>
<hr>
<p>Thanks for all the feedback though - really helpful for thinking through these design decisions! <img src="https://forum.elixirforum.com/images/emoji/apple/slight_smile.png?v=15" title=":slight_smile:" class="emoji" alt=":slight_smile:" loading="lazy" width="20" height="20"></p> 
	            </div>

	            <div class="base-line">
	                <div class="thread-counters">
	                    <span class="thread-count count-likes js-likers-trigger" title="Likes" data-post-id="374781" 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/time-for-hologram-javascript-interop-what-would-you-like-to-see/72518/47">Post #46</a>
	                </div>
	            </div>
              <div id="likers-container-374781" 
                   class="likers-container"
                   data-first-post="false"
                   data-batch-url="/posts/batch_likers">
                   <div class="likers-placeholder" 
                     data-likers-post-id="374781"
                     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 #46"></div>
  </section>
</div>
    <div class="postbit" id="374804" data-post-id="374804">
  <section>
    <div class="post-wrap">


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

	        <div class="thread-main">
	            <div class="post-body" data-turbo="false">
								<aside class="quote no-group" data-username="bartblast" data-post="44" data-topic="72518">
<div class="title">
<div class="quote-controls"></div>
<img alt="" width="24" height="24" src="https://forum.elixirforum.com/user_avatar/forum.elixirforum.com/bartblast/48/17647_2.png" class="avatar"> bartblast:</div>
<blockquote>
<p>But here’s where I see the tradeoff: events force async communication even when you just need to call a simple synchronous function.</p>
</blockquote>
</aside>
<p>FWIW, this particular part of the discussion reminds me of the JS interop situation in Elm; short short version Elm chose to require it to go through “ports” that are async. It was not a decision that everybody in the community agreed with, you can read lots of blog posts about both sides.</p> 
	            </div>

	            <div class="base-line">
	                <div class="thread-counters">
	                    <span class="thread-count count-likes js-likers-trigger" title="Likes" data-post-id="374804" 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/time-for-hologram-javascript-interop-what-would-you-like-to-see/72518/48">Post #47</a>
	                </div>
	            </div>
              <div id="likers-container-374804" 
                   class="likers-container"
                   data-first-post="false"
                   data-batch-url="/posts/batch_likers">
                   <div class="likers-placeholder" 
                     data-likers-post-id="374804"
                     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 #47"></div>
  </section>
</div>
    <div class="postbit" id="375893" data-post-id="375893">
  <section>
    <div class="post-wrap">


					<div class="post-header">
		        <div class="user-avatar">
		          <img alt="bartblast" src="https://forum.elixirforum.com/user_avatar/forum.elixirforum.com/bartblast/120/17647_2.png" width="120" height="120" />
		        </div>
					
						<div class="user-details">
		          <div class="user-name">
		            <h3>
                  bartblast
                    <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 class="user-title">
									<span>Creator of Hologram</span>
			          </div>
						</div>
					
					</div>

	        <div class="thread-main">
	            <div class="post-body" data-turbo="false">
								<aside class="quote no-group" data-username="tozz" data-post="45" data-topic="72518" data-full="true">
<div class="title">
<div class="quote-controls"></div>
<img alt="" width="24" height="24" src="https://forum.elixirforum.com/letter_avatar_proxy/v4/letter/t/a8b319/48.png" class="avatar"> tozz:</div>
<blockquote>
<p>Interesting discussions, I think one key aspect is to make sure you can store the JS return values and use them in later calls, or maybe you already thought about that?</p>
<p>Let’s say you do <code>chart = JS.new(“ChartLibrary”, [{data: nil}]</code> and then in somewhere later you want to access <code>chart</code> and do something like <code>JS.call(chart, "populateData", [...])</code> on it, how would that work?</p>
</blockquote>
</aside>
<p>Yeah, that should work out of the box the way you described 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="375893" 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/time-for-hologram-javascript-interop-what-would-you-like-to-see/72518/49">Post #48</a>
	                </div>
	            </div>
              <div id="likers-container-375893" 
                   class="likers-container"
                   data-first-post="false"
                   data-batch-url="/posts/batch_likers">
                   <div class="likers-placeholder" 
                     data-likers-post-id="375893"
                     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 #48"></div>
  </section>
</div>
    <div class="postbit" id="375895" data-post-id="375895">
  <section>
    <div class="post-wrap">


					<div class="post-header">
		        <div class="user-avatar">
		          <img alt="bartblast" src="https://forum.elixirforum.com/user_avatar/forum.elixirforum.com/bartblast/120/17647_2.png" width="120" height="120" />
		        </div>
					
						<div class="user-details">
		          <div class="user-name">
		            <h3>
                  bartblast
                    <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 class="user-title">
									<span>Creator of Hologram</span>
			          </div>
						</div>
					
					</div>

	        <div class="thread-main">
	            <div class="post-body" data-turbo="false">
								<aside class="quote no-group quote-modified" data-username="al2o3cr" data-post="48" data-topic="72518" data-full="true">
<div class="title">
<div class="quote-controls"></div>
<img alt="" width="24" height="24" src="https://forum.elixirforum.com/user_avatar/forum.elixirforum.com/al2o3cr/48/3457_2.png" class="avatar"> al2o3cr:</div>
<blockquote>
<aside class="quote no-group" data-username="bartblast" data-post="44" data-topic="72518">
<div class="title">
<div class="quote-controls"></div>
<img alt="" width="24" height="24" src="https://forum.elixirforum.com/user_avatar/forum.elixirforum.com/bartblast/48/17647_2.png" class="avatar"> bartblast:</div>
<blockquote>
<p>But here’s where I see the tradeoff: events force async communication even when you just need to call a simple synchronous function.</p>
</blockquote>
</aside>
<p>FWIW, this particular part of the discussion reminds me of the JS interop situation in Elm; short short version Elm chose to require it to go through “ports” that are async. It was not a decision that everybody in the community agreed with, you can read lots of blog posts about both sides.</p>
</blockquote>
</aside>
<p>Yeah, exactly - I’m well aware of how polarizing this was in the Elm community. Anecdotally, I recently talked to a CTO from a fairly significant startup who wanted to migrate their LiveView app to Hologram, and when I mentioned I was considering modeling JS interop after Elm ports, he nearly rolled his eyes <img src="https://forum.elixirforum.com/images/emoji/apple/rofl.png?v=15" title=":rofl:" class="emoji" alt=":rofl:" loading="lazy" width="20" height="20"> (he worked with Elm ports in the past).</p>
<p>Ports solved a problem for Elm’s constraints, but the developer experience cost was real and memorable enough that it’s one of the first things people bring up years later.</p>
<p>That said, I’m not ruling out async-only approaches entirely - there are genuine benefits to that constraint (it does force better separation of concerns). But I’m also not convinced it has to be the only tool in the toolbox. I think we can offer both patterns: straightforward sync calls for simple operations, and event-based patterns for stateful, complex interactions with JS libraries.</p>
<p>The key is making sure whatever we build here doesn’t create the same “if only I could just call this function directly” frustration that accumulated over time in the Elm ecosystem.</p> 
	            </div>

	            <div class="base-line">
	                <div class="thread-counters">
	                    <span class="thread-count count-likes js-likers-trigger" title="Likes" data-post-id="375895" 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/time-for-hologram-javascript-interop-what-would-you-like-to-see/72518/50">Post #49</a>
	                </div>
	            </div>
              <div id="likers-container-375895" 
                   class="likers-container"
                   data-first-post="false"
                   data-batch-url="/posts/batch_likers">
                   <div class="likers-placeholder" 
                     data-likers-post-id="375895"
                     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 #49"></div>
  </section>
</div>
    <div class="postbit" id="375896" data-post-id="375896">
  <section>
    <div class="post-wrap">


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

	        <div class="thread-main">
	            <div class="post-body" data-turbo="false">
								<p>fwiw, I think your instincts are spot on. I worked with a team that used Elm and the JS interop seemed to be a source of frustration.</p> 
	            </div>

	            <div class="base-line">
	                <div class="thread-counters">
	                    <span class="thread-count count-likes js-likers-trigger" title="Likes" data-post-id="375896" 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/time-for-hologram-javascript-interop-what-would-you-like-to-see/72518/51">Post #50</a>
	                </div>
	            </div>
              <div id="likers-container-375896" 
                   class="likers-container"
                   data-first-post="false"
                   data-batch-url="/posts/batch_likers">
                   <div class="likers-placeholder" 
                     data-likers-post-id="375896"
                     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 #50"></div>
  </section>
</div>
    <div class="postbit" id="383560" data-post-id="383560">
  <section>
    <div class="post-wrap">


					<div class="post-header">
		        <div class="user-avatar">
		          <img alt="bartblast" src="https://forum.elixirforum.com/user_avatar/forum.elixirforum.com/bartblast/120/17647_2.png" width="120" height="120" />
		        </div>
					
						<div class="user-details">
		          <div class="user-name">
		            <h3>
                  bartblast
                    <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 class="user-title">
									<span>Creator of Hologram</span>
			          </div>
						</div>
					
					</div>

	        <div class="thread-main">
	            <div class="post-body" data-turbo="false">
								<p>Quick update: I’m starting to code the JS interop! Stay tuned <img src="https://forum.elixirforum.com/images/emoji/apple/slight_smile.png?v=15" title=":slight_smile:" class="emoji" alt=":slight_smile:" loading="lazy" width="20" height="20"></p> 
	            </div>

	            <div class="base-line">
	                <div class="thread-counters">
	                    <span class="thread-count count-likes js-likers-trigger" title="Likes" data-post-id="383560" data-batch-url="/posts/batch_likers">
                        11
                      </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/time-for-hologram-javascript-interop-what-would-you-like-to-see/72518/52">Post #51</a>
	                </div>
	            </div>
              <div id="likers-container-383560" 
                   class="likers-container"
                   data-first-post="false"
                   data-batch-url="/posts/batch_likers">
                   <div class="likers-placeholder" 
                     data-likers-post-id="383560"
                     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 #51"></div>
  </section>
</div>
    <div class="postbit" id="383627" data-post-id="383627">
  <section>
    <div class="post-wrap">


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

	        <div class="thread-main">
	            <div class="post-body" data-turbo="false">
								<p>Exciting news!</p> 
	            </div>

	            <div class="base-line">
	                <div class="thread-counters">
	                    <span class="thread-count count-likes js-likers-trigger" title="Likes" data-post-id="383627" 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/time-for-hologram-javascript-interop-what-would-you-like-to-see/72518/53">Post #52</a>
	                </div>
	            </div>
              <div id="likers-container-383627" 
                   class="likers-container"
                   data-first-post="false"
                   data-batch-url="/posts/batch_likers">
                   <div class="likers-placeholder" 
                     data-likers-post-id="383627"
                     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 #52"></div>
  </section>
</div>
    <div class="postbit" id="384830" data-post-id="384830">
  <section>
    <div class="post-wrap">


					<div class="post-header">
		        <div class="user-avatar">
		          <img alt="bartblast" src="https://forum.elixirforum.com/user_avatar/forum.elixirforum.com/bartblast/120/17647_2.png" width="120" height="120" />
		        </div>
					
						<div class="user-details">
		          <div class="user-name">
		            <h3>
                  bartblast
                    <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 class="user-title">
									<span>Creator of Hologram</span>
			          </div>
						</div>
					
					</div>

	        <div class="thread-main">
	            <div class="post-body" data-turbo="false">
								<p>JS interop shipped in v0.8.0! <img src="https://forum.elixirforum.com/images/emoji/apple/slight_smile.png?v=15" title=":slight_smile:" class="emoji" alt=":slight_smile:" loading="lazy" width="20" height="20"></p> 
	            </div>

	            <div class="base-line">
	                <div class="thread-counters">
	                    <span class="thread-count count-likes js-likers-trigger" title="Likes" data-post-id="384830" 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/time-for-hologram-javascript-interop-what-would-you-like-to-see/72518/54">Post #53</a>
	                </div>
	            </div>
              <div id="likers-container-384830" 
                   class="likers-container"
                   data-first-post="false"
                   data-batch-url="/posts/batch_likers">
                   <div class="likers-placeholder" 
                     data-likers-post-id="384830"
                     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>