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


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

	        <div class="thread-main">
	            <div class="post-body" data-turbo="false">
								<p>You can store anything in the socket, but the point is to auth the client as soon as he come in, so something has to be on the client side, be it cookie or localStorage. And once the client is auth’ed. you don’t need to store the token anymore, just the auth’ed state and his account details.</p> 
	            </div>

	            <div class="base-line">
	                <div class="thread-counters">
	                    <span class="thread-count count-likes js-likers-trigger" title="Likes" data-post-id="213029" 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/surface-a-component-based-library-for-phoenix-liveview/27671/114">Post #113</a>
	                </div>
	            </div>
              <div id="likers-container-213029" 
                   class="likers-container"
                   data-first-post="false"
                   data-batch-url="/posts/batch_likers">
                   <div class="likers-placeholder" 
                     data-likers-post-id="213029"
                     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 #113"></div>
  </section>
</div>
    <div class="postbit" id="213414" data-post-id="213414">
  <section>
    <div class="post-wrap">


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

	        <div class="thread-main">
	            <div class="post-body" data-turbo="false">
								<p>On the topic of mixing <code>Surface.LiveView</code>s with classic (dead <em>giggle</em>) views, is there a way to tell Surface to use a <code>live.html</code> layout by default?</p>
<p>I know I can tell each individual module to:</p>
<pre data-code-wrap="elixir"><code class="lang-elixir">  use Surface.LiveView,
    layout: {PlatformWeb.LayoutView, "live.html"}
</code></pre>
<p>But can I do it globally?</p>
<p>For plain LiveView we would do:</p>
<pre data-code-wrap="elixir"><code class="lang-elixir">  def live_view do
    quote do
      use Phoenix.LiveView,
        layout: {PlatformWeb.LayoutView, "live.html"}

      unquote(view_helpers())
    end
  end
</code></pre>
<p>in our <code>myapp_web.ex</code>.</p>
<p>Is there an equivalent for surface?</p> 
	            </div>

	            <div class="base-line">
	                <div class="thread-counters">
	                    <span class="thread-count count-likes js-likers-trigger" title="Likes" data-post-id="213414" 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/surface-a-component-based-library-for-phoenix-liveview/27671/115">Post #114</a>
	                </div>
	            </div>
              <div id="likers-container-213414" 
                   class="likers-container"
                   data-first-post="false"
                   data-batch-url="/posts/batch_likers">
                   <div class="likers-placeholder" 
                     data-likers-post-id="213414"
                     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 #114"></div>
  </section>
</div>
    <div class="postbit" id="213417" data-post-id="213417">
  <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>Just replace <code>use Phoenix.LiveView</code> in the <code>live_view</code> macro with <code>use Surface.LiveView</code></p>
<p>or make a new macro for <code>:surface_live_view</code></p>
<pre data-code-wrap="elixir"><code class="lang-elixir">  def surface_live_view do
    quote do
      use Surface.LiveView,
        layout: {PlatformWeb.LayoutView, "live.html"}

      unquote(view_helpers())
    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="213417" 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/surface-a-component-based-library-for-phoenix-liveview/27671/116">Post #115</a>
	                </div>
	            </div>
              <div id="likers-container-213417" 
                   class="likers-container"
                   data-first-post="false"
                   data-batch-url="/posts/batch_likers">
                   <div class="likers-placeholder" 
                     data-likers-post-id="213417"
                     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 #115"></div>
  </section>
</div>
    <div class="postbit" id="213420" data-post-id="213420">
  <section>
    <div class="post-wrap">


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

	        <div class="thread-main">
	            <div class="post-body" data-turbo="false">
								<aside class="quote no-group" data-username="mfilej" data-post="115" data-topic="27671">
<div class="title">
<div class="quote-controls"></div>
<img alt="" width="24" height="24" src="https://forum.elixirforum.com/user_avatar/forum.elixirforum.com/mfilej/48/6517_2.png" class="avatar"> mfilej:</div>
<blockquote>
<p>is there a way to tell Surface to use a <code>live.html</code> layout by default?</p>
</blockquote>
</aside>
<p>The concept of a layout is obsolete in Surface. With a Surface component you can have multiple, named slots, much more expressive than a single <code>&lt;%= @inner_content %&gt;</code></p> 
	            </div>

	            <div class="base-line">
	                <div class="thread-counters">
	                    <span class="thread-count count-likes js-likers-trigger" title="Likes" data-post-id="213420" 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/surface-a-component-based-library-for-phoenix-liveview/27671/117">Post #116</a>
	                </div>
	            </div>
              <div id="likers-container-213420" 
                   class="likers-container"
                   data-first-post="false"
                   data-batch-url="/posts/batch_likers">
                   <div class="likers-placeholder" 
                     data-likers-post-id="213420"
                     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 #116"></div>
  </section>
</div>
    <div class="postbit" id="213489" data-post-id="213489">
  <section>
    <div class="post-wrap">


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

	        <div class="thread-main">
	            <div class="post-body" data-turbo="false">
								<aside class="quote no-group" data-username="derek-zhou" data-post="117" data-topic="27671">
<div class="title">
<div class="quote-controls"></div>
<img alt="" width="24" height="24" src="https://forum.elixirforum.com/user_avatar/forum.elixirforum.com/derek-zhou/48/19943_2.png" class="avatar"> derek-zhou:</div>
<blockquote>
<p>The concept of a layout is obsolete in Surface. With a Surface component you can have multiple, named slots, much more expressive than a single <code>&lt;%= @inner_content %&gt;</code></p>
</blockquote>
</aside>
<p>I see what you mean, but I don’t know how to set that up? I have a parent .html.eex layout that is shared between classic controllers and Surface.LiveViews. Now I need a way to output the live_flash only for LiveViews (what <code>live.html</code> does if you generate a new phoenix app with --live).</p> 
	            </div>

	            <div class="base-line">
	                <div class="thread-counters">
	                    <span class="thread-count count-likes js-likers-trigger" title="Likes" data-post-id="213489" 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/surface-a-component-based-library-for-phoenix-liveview/27671/118">Post #117</a>
	                </div>
	            </div>
              <div id="likers-container-213489" 
                   class="likers-container"
                   data-first-post="false"
                   data-batch-url="/posts/batch_likers">
                   <div class="likers-placeholder" 
                     data-likers-post-id="213489"
                     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 #117"></div>
  </section>
</div>
    <div class="postbit" id="213533" data-post-id="213533">
  <section>
    <div class="post-wrap">


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

	        <div class="thread-main">
	            <div class="post-body" data-turbo="false">
								<p>If you just need the flash, you can do:</p>
<p>main.sface:</p>
<pre data-code-wrap="elixir"><code class="lang-elixir">&lt;div id="main-content" class="content" phx-hook="Main"&gt;
    &lt;div role="alert" :for={{ type &lt;- Map.keys(@messages) }}
       class={{ "alert", alert_class(type) }}
       phx-value-key={{ type }} phx-click="lv:clear-flash"&gt;
        {{ @messages[type] }}
    &lt;/div&gt;
    &lt;slot /&gt;
&lt;/div&gt;
</code></pre>
<p>include a Main component in your liveviews::</p>
<pre data-code-wrap="elixir"><code class="lang-elixir">&lt;Main :props={{ messages: @flash }}&gt;
YOUR STUFF
&lt;/Main&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="213533" 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/surface-a-component-based-library-for-phoenix-liveview/27671/119">Post #118</a>
	                </div>
	            </div>
              <div id="likers-container-213533" 
                   class="likers-container"
                   data-first-post="false"
                   data-batch-url="/posts/batch_likers">
                   <div class="likers-placeholder" 
                     data-likers-post-id="213533"
                     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 #118"></div>
  </section>
</div>
    <div class="postbit" id="213535" data-post-id="213535">
  <section>
    <div class="post-wrap">


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

	        <div class="thread-main">
	            <div class="post-body" data-turbo="false">
								<aside class="quote no-group" data-username="derek-zhou" data-post="119" data-topic="27671">
<div class="title">
<div class="quote-controls"></div>
<img alt="" width="24" height="24" src="https://forum.elixirforum.com/user_avatar/forum.elixirforum.com/derek-zhou/48/19943_2.png" class="avatar"> derek-zhou:</div>
<blockquote>
<p>include a Main component in your liveviews::</p>
</blockquote>
</aside>
<p>Hmm, but then I’d have to repeat that in every LiveView? For now I’ve resorted to <a class="mention" href="/u/harmon25" rel="nofollow">@harmon25</a>’s trick with <code>:surface_live_view</code> (thanks!).</p> 
	            </div>

	            <div class="base-line">
	                <div class="thread-counters">
	                    <span class="thread-count count-likes js-likers-trigger" title="Likes" data-post-id="213535" 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/surface-a-component-based-library-for-phoenix-liveview/27671/120">Post #119</a>
	                </div>
	            </div>
              <div id="likers-container-213535" 
                   class="likers-container"
                   data-first-post="false"
                   data-batch-url="/posts/batch_likers">
                   <div class="likers-placeholder" 
                     data-likers-post-id="213535"
                     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 #119"></div>
  </section>
</div>
    <div class="postbit" id="213536" data-post-id="213536">
  <section>
    <div class="post-wrap">


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

	        <div class="thread-main">
	            <div class="post-body" data-turbo="false">
								<p>I prefer explicit specification over implicit. Also with Liveview I typically have far fewer LiveViews than classical controller/view pairs.</p> 
	            </div>

	            <div class="base-line">
	                <div class="thread-counters">
	                    <span class="thread-count count-likes js-likers-trigger" title="Likes" data-post-id="213536" 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/surface-a-component-based-library-for-phoenix-liveview/27671/121">Post #120</a>
	                </div>
	            </div>
              <div id="likers-container-213536" 
                   class="likers-container"
                   data-first-post="false"
                   data-batch-url="/posts/batch_likers">
                   <div class="likers-placeholder" 
                     data-likers-post-id="213536"
                     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 #120"></div>
  </section>
</div>
    <div class="postbit" id="214039" data-post-id="214039">
  <section>
    <div class="post-wrap">


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

	        <div class="thread-main">
	            <div class="post-body" data-turbo="false">
								<p><a class="mention" href="/u/mfilej" rel="nofollow">@mfilej</a> I also use the suggestion of <a class="mention" href="/u/derek-zhou" rel="nofollow">@derek-zhou</a></p>
<p>In most app I develop, I need several layouts as they deserve different purpose, and most importantly, they have different designs.</p>
<p>I often use 3 types of layout:</p>
<ul>
<li>a <code>LandingLayout</code> that is used only for the landing page of the website and any related stuff:
<ul>
<li>marketing-oriented design</li>
<li>few user interactions</li>
<li>components are not reused</li>
</ul>
</li>
<li>a <code>AppLayout</code> or <code>MainLayout</code> that is used in the application itself when the user is connected
<ul>
<li>UX oriented design</li>
<li>a lot of user interactions</li>
<li>components are reused everywhere in the app</li>
</ul>
</li>
<li>an <code>AdminLayout</code> that is used only by the team
<ul>
<li>Ugly design (^^)</li>
<li>medium user interactions</li>
<li>components are reused in the backend</li>
</ul>
</li>
</ul>
<p>By opening one of my live view, it’s really clear for me which layout is used on and what are the features that layout gives me access to!</p>
<p>In 80% of the time, my live views look like this</p>
<pre data-code-wrap="html"><code class="lang-html">&lt;AppLayout
  flashes={{ @flash }}
  current_user={{ @current_user }}
/&gt;
  My Content
&lt;/AppLayout&gt;
</code></pre>
<p>In the 20 remaining %, I am able to tweak my layout for specific pages explicitly without duplicating it.</p>
<pre data-code-wrap="html"><code class="lang-html">&lt;AppLayout
  show_sidebar={{ false }} &lt;-- NO SIDEBAR FOR THAT LIVE VIEW
  flashes={{ @flash }}
  current_user={{ @current_user }}
/&gt;
  My content

  &lt;PageTitle&gt;
    Override the design of the page title for that specific live view
  &lt;/PageTitle&gt;

  &lt;RightColumn&gt;
    Useful slottable component that extends my layout and that is not present by default
  &lt;/RightColumn&gt;
  # or
  &lt;ProfileRightColumn user={{ current_user }} /&gt; &lt;-- A PREDIFINED RIGHT COLUMN THAT IS EXPLICIT OF ITS INTENT (It is "just" a wrapper arround `&lt;RightColumn&gt;...&lt;/RightColumn&gt;` with predifined `props`
&lt;/AppLayout&gt;
</code></pre>
<p>Finally, here is an example of one of my layout with some comments (I removed classes and I only show the render function):</p>
<pre data-code-wrap="html"><code class="lang-html">      &lt;div
        x-data="{ open: false }"
        @keydown.window.escape="open = false"
      &gt;
        &lt;slot name="sidebar" :if={{ @show_sidebar }}&gt; &lt;-- WRAPPING COMPONENTS INTO A SLOT ALLOWS ME TO OVERRIDE THEM EASILY
          &lt;Sidebar id="sidebar" /&gt;
        &lt;/slot&gt;

        &lt;slot name="secondary_sidebar" /&gt; &lt;-- OPTIONAL EXTENSION

        &lt;div&gt;
          &lt;slot name="header_menu"&gt; &lt;-- LIKE SIDEBAR, IF THE HEADER HAS NOT BEEN OVERRIDED, SHOW THE DEFAULT ONE
            &lt;HeaderMenu id="header-menu" /&gt;
          &lt;/slot&gt;

          &lt;!-- Main content --&gt;
          &lt;div&gt;

            &lt;!-- Primary column --&gt;
            &lt;main&gt;
              &lt;section&gt;
                &lt;h1&gt;{{ @page_title }}&lt;/h1&gt; &lt;-- PROP FOR THAT LAYOUT
                &lt;slot name="default" /&gt; &lt;-- MAIN CONTENT
              &lt;/section&gt;
            &lt;/main&gt;

            &lt;!-- Optional secondary column --&gt;
            &lt;slot
              name="secondary_column"
              :if={{ show_secondary_column(assigns) }} /&gt; &lt;-- OPTIONNAL EXTENSION WHOSE VISIBILITY IS MANAGED BY THE CHILD COMPONENT
          &lt;/div&gt;
        &lt;/div&gt;
      &lt;/div&gt;
      &lt;FlashMessages flashes={{ @flashes }} /&gt; &lt;-- FLASHES WRAPPER
</code></pre>
<p>So yes you have to repeat a few lines of code, but I really believe you gain in clarity and in functionality <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>
<p>Hope this will help other Surface users! Feel free to comment and get my yours feedback !</p> 
	            </div>

	            <div class="base-line">
	                <div class="thread-counters">
	                    <span class="thread-count count-likes js-likers-trigger" title="Likes" data-post-id="214039" data-batch-url="/posts/batch_likers">
                        10
                      </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/surface-a-component-based-library-for-phoenix-liveview/27671/122">Post #121</a>
	                </div>
	            </div>
              <div id="likers-container-214039" 
                   class="likers-container"
                   data-first-post="false"
                   data-batch-url="/posts/batch_likers">
                   <div class="likers-placeholder" 
                     data-likers-post-id="214039"
                     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 #121"></div>
  </section>
</div>
    <div class="postbit" id="214839" data-post-id="214839">
  <section>
    <div class="post-wrap">


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

	        <div class="thread-main">
	            <div class="post-body" data-turbo="false">
								<p>Just started really playing around with Surface, and gotta say nice work y’all! It’s <em>really</em> nice to have typed templates.</p>
<p>I’ve created a few widgets to help with standard IoT/Dashboard things I build a lot (for work and personal), see <a href="https://github.com/elcritch/surface_bulma_widgets" rel="noopener nofollow ugc">SurfaceBulmaWidgets</a>. Warning, they probably break a few best practices. <img src="https://forum.elixirforum.com/images/emoji/apple/wink.png?v=15" title=":wink:" class="emoji" alt=":wink:" loading="lazy" width="20" height="20"></p>
<p>What I really wanted to share for others was a “bind” concept and macro implementation. See <a href="https://github.com/elcritch/surface_bulma_widgets/blob/main/lib/surface_bulma_widgets/bindings.ex" rel="noopener nofollow ugc">SurfaceBulmaWidgets.Bindings</a>. It draws on my previous experience writing <a href="https://github.com/elcritch/bulma_widgets" rel="noopener nofollow ugc">bulma_widgets</a> (which was pre-live-components IIRC).</p>
<p><code>SurfaceBulmaWidgets.Bindings</code> takes/passes the name of the variable along with it’s value to the child <em>widget</em> (currently Surface.LiveComponent’s). The <em>widget</em> then sends the parent a standardized event <code>{:update_bind, name, value}</code>.</p>
<p>It’s somewhat like <code>contexts</code> but I prefer having a standard event and not needing to pass entire contexts around. It’s basically Vue’s <code>bind</code> mechanism.</p>
<pre data-code-wrap="elixir"><code class="lang-elixir">defmodule SurfaceBulmaWidgetsPlaygroundWeb.HomePageLive do
  use Surface.LiveView
  require Logger
  use SurfaceBulmaWidgets

  alias Surface.Components.LiveRedirect
  alias SurfaceBulmaWidgets.Layouts.{Columns, Column}
  alias SurfaceBulmaWidgets.UI.{RangedSlider, NumberDisplay|

  data count1, :integer, default: 10
  data count2, :integer, default: 80

  def render(assigns) do
    ~H"""
      &lt;Columns multiline&gt;
        &lt;Column width=4&gt;
          &lt;div class="box" &gt;
            &lt;p&gt;Example Reactive Widgets&lt;/p&gt;

            &lt;RangedSlider id="rl1" var={{bind(@count1)}}/&gt;
            &lt;RangedSlider id="rl2" var={{bind(@count2)}}/&gt;
            &lt;NumberDisplay id="ndl2" name="Count 2" value={{bind(@count2)}} digits=1/&gt;
            &lt;p&gt;&lt;LiveRedirect label="Learn more" to="/uicomponents" /&gt;&lt;/p&gt;
          &lt;/div&gt;
        &lt;/Column&gt;
      &lt;/Columns&gt;
    """
  end

  # Override: `handle_info({:update_bind, name, value} = msg, socket)` for custom behavior
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="214839" 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/surface-a-component-based-library-for-phoenix-liveview/27671/123">Post #122</a>
	                </div>
	            </div>
              <div id="likers-container-214839" 
                   class="likers-container"
                   data-first-post="false"
                   data-batch-url="/posts/batch_likers">
                   <div class="likers-placeholder" 
                     data-likers-post-id="214839"
                     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 #122"></div>
  </section>
</div>
</template></turbo-stream><turbo-stream action="replace" target="load-more-container"><template><div id="load-more-container" class="load-more-container">
    <a class="load-more-button" data-turbo-stream="true" href="/topics/27671/load_more?page=13">Load more posts (94 remaining)</a>
</div></template></turbo-stream>