OvermindDL1

OvermindDL1

We’ve been using WebComponents a lot lately at our place of work and sadly using the phoenix socket library threaded through everything is not very reusable, so ended up making a webcomponent of the phoenix socket itself. So we can just do something like this in html:

        <phoenix-socket
          endpoint="/socket"
          param-token="<%= Guardian.Plug.current_token(@conn) %>"
          connected="{{socketConnected}}"
          socket="{{socket}}"
          connect
          ></phoenix-socket>
          EndPoint: "[[socket.endPoint]]"<br />
          IsConnected: "[[socketConnected]]"<br />

And this, in this case, outputs this to the screen:

EndPoint: "/socket/websocket"
IsConnected: "true"

Of course changing any of the properties like endpoint or parameters or disabling ‘connect’ or so will cause it to disconnect and/or reconnect with new parameters, but for a socket that is a rare case anyway.

We can continue to thread to join a topic like:

    <phoenix-channel
      socket="{{socket}}"
      channel="{{channel}}"
      topic-pre="Messenger:"
      topic="system"
      msg-joined="{{msgJoined}}"
      connected="{{topicSystemConnected}}"
      ></phoenix-channel>
    System Topic Joined:  [[topicSystemConnected]] <br />
    Your nick:  [[msgJoined.nick]]

Which outputs this (since the server "Messenger:system" topic returns a structure that contains your nick):

System Topic Joined: true
Your nick: Gabriel Robertson

The {{socket}} here is the same variable that is from the <phoenix-socket />, you can pass in the normal Phoenix library socket object as well if you are using an existing library elsewhere and want to re-use the socket, or you can take this socket and give it to normal javascript code elsewhere. And as expected if you add a sleep or something to the socket join then the ‘true’ above will be ‘false’ until the join finally goes through. It automatically handles new sockets, no sockets, sockets losing and reconnecting its connection, etc… Also handles changing properties will disconnect and reconnect to a new given topic with whatever parameters are specified as expected. You can get various topic information here (like with the socket, the channel has a lot more options that are not demonstrated here, still need to program in more as well).

To handle messages you can use javascript to listen as normal, or continue using html by doing:

<phoenix-msghandler
  channel="{{channel}}"
  key="msg:recv"
  msg="{{receivedMsg}}"
  ></phoenix-msghandler>

And similar for presence as well, takes the channel output from the above <phoenix-channel /> as input, or feel free to pass in your own channel object via javascript. Usual property stuff. Etc…

Do many other people use webcomponents here and might find these useful?

Showing Posts 1 to 5

OvermindDL1

OvermindDL1 OP

I’ve made a testing SPA that is server driven using webcomponents. The links at the top are normal ‘a’ links (middle-clickable and all), just instead of routing they are matched out and sent to the server via a <phoenix-channel-msg> element. The server sends a map of “importURLs” and “elementName” and optionally “cmds”, the SPA will import those url’s if not already imported then it will create the given element and replace the on-page ‘page’ element with (using css effect to slide out and in, just because I could ^.^) once it fully loaded. There is no flash of unstyled content, everything is fast and easily cachable and mix phoenix.digestable, all communication happens over a phoenix websocket/longpolling, tested in Chrome, Firefox, Edge (the below animation is edge, it is actually a lot smoother than the animation shows), IE11, and Chrome on my android phone:

The Root link is just “/spa”, the Root with slash link is “/spa/” (I was trying to test all cases), Messenger is “/spa/messenger”, and Blah is “/spa/blah”. Blah does not exist on the server so it sends back a thing to display the error module (which I’ve not implemented yet so it falls back to blank and logs a message in the console right now), but messenger displays another module that sets up another phoenix channel connection over the same socket, and the root’s just display the ‘home’ page, which is just some text right now. I have some descriptive text showing the state of some of the bindings.

The useful bit of the html is just this:

    <app-location route="{{fullRoute}}" url-space-regex="[[basePath]]"></app-location>
    <app-route id="baseRoute"
      route="{{fullRoute}}"
      pattern="[[basePath]]"
      tail="{{baseRoute}}"
      active="{{baseRouteActive}}"
      ></app-route>
    <app-route id="route"
      route="{{baseRoute}}"
      pattern="/:name"
      data="{{moduleRouteData}}"
      tail="{{moduleRoute}}"
      active="{{moduleRouteActive}}"
      ></app-route>

    <phoenix-socket id="socket"
      endpoint="/socket"
      param-token="[[paramToken]]"
      connected="{{socketConnected}}"
      socket="{{socket}}"
      connect="true"
      ></phoenix-socket>

    <phoenix-channel
      socket="{{socket}}"
      channel="{{controlChannel}}"
      topic="spa"
      msg-joined="{{controlChannelMsgJoined}}"
      connected="{{controlChannelConnected}}"
      ></phoenix-channel>
    <phoenix-channel-msg
      channel="{{controlChannel}}"
      event="view"
      msg-send="{{moduleRouteData.name}}"
      msg-latest="{{mainViewData}}"
      ></phoenix-channel-msg>

    <app-drawer-layout id="layout" responsive-width="1280px">
      <app-drawer swipe-open>
        <app-header condenses reveals shadow effects="waterfall">
          <app-toolbar style="pointer-events:all;">
            <a main-title href="/" class="site-title">/* Snip */</a>
          </app-toolbar>
        </app-header>
        <div style="height: 100%; overflow: auto;">Testing a drawer</div>
      </app-drawer>
      <app-header-layout>
        <app-header condenses reveals shadow effects="waterfall">
          <app-toolbar style="pointer-events:all;">
            <paper-icon-button icon="menu" drawer-toggle></paper-icon-button>
            <a main-title href="/" class="site-title">/* Snip */</a>
          </app-toolbar>
        </app-header>
        <main role="main">

          <a href="[[basePath]]">Root</a><br />
          <a href="[[basePath]]/">Root with slash</a><br />
          <a href="[[basePath]]/messenger">Messenger</a><br />
          <a href="[[basePath]]/blah">Blah</a><br />

          Token: "[[paramToken]]"<br />
          BasePath: "[[basePath]]"<br />
          Module Name: "[[moduleRouteData.name]]" -> [[_stringify(moduleRouteData)]]<br />
          Module Path: "[[moduleRoute.path]]"<br />
          Socket: "[[socket]]"<br />
          EndPoint: "[[socket.endPoint]]"<br />
          IsConnected: [[socketConnected]] -> [[controlChannelConnected]] -> [[_stringify(controlChannelMsgJoined)]]<br />
          MainViewData: [[_stringify(mainViewData)]]<br />
          ModuleRouteActive:  [[moduleRouteActive]]<br />
          <neon-animated-pages
            id="moduleContainer"
            attr-for-selected="module"
            selected=""
            on-neon-animation-finish="_onNeonAnimationFinish"
            entry-animation="slide-from-right-animation"
            exit-animation="slide-left-animation"
            animate-initial-selection></neon-animated-pages>
        </main>
      </app-header-layout>
    </app-drawer-layout>

And Phoenix is currently routing all “/spa” and “/spa/*path” requests to that same template, the router on the page uses the route to contact the server to determine what to display. I have a few modules though I’m just testing some of the test links in the animation (and removed the work branding and such).

gpb

gpb

Very cool. I’ve been learning React Native for a small mobile project, but a big-shot friend in San Francisco is pushing me to get into Polymer and WebComponents.

Would be very interested to see this up on GitHub someday.

andre1sk

andre1sk

Those are very different with React Native you are actually using native widgets. React Native is really fun to develop in compared to fully native too.

cpgo

cpgo

Can you share a public repo? This is very interesting.

OvermindDL1

OvermindDL1 OP

I plan to pull out the phoenix socket webcomponents out once I’ve finished well testing them. I seemingly keep finding random little bugs of my own doing every time I stress them, though not in over a week now so they might be good. Still some new features I want to add though, but those are pretty optional, I could release it now, hmm…

— All posts loaded —

Where Next? Top

Trending in Discussions Top

AstonJ
As the title says, please share what you’ve been up to with Elixir. Whether that’s been learning it, looking into it, making stuff with i...
2977 91898 914
New
AstonJ
The obligatory hello world thread! Who are you and where are you from? :stuck_out_tongue:
4616 55835 594
New
byu
@chrismccord : I just saw the Extract AGENTS.md from Phoenix.new into phx.new generator commit to the phoenix project. My initial shotgu...
New
arcanemachine
I was working on an Ecto migration and I needed a timestamp. So, for the nth time, I looked up the different data types for timestamps, a...
New
alexslade
Fly’s CEO posted this recently - Turn And Face The Strange · The Fly Blog It says that Fly is going all-in on sprites, which is a worry ...
New
Herve37
We’re evaluating API mocking tools for OpenAPI-based projects and would love to hear what other teams are using. We’re particularly inte...
New
matt-savvy
Is there a word for the ~> symbol used in Version strings? Do you also just call it a Squiggle Arrow™ ?!
New

Other Trending Topics Top

JesseHerrick
Hey, I’m Jesse and I’m the main contributor behind Dexter, a full-featured, lightning-fast Elixir LSP optimized for large codebases. It s...
New
jimsynz
Beam Bots (or just BB for short) is a framework for building fault-tolerant robotics applications in Elixir using familiar OTP patterns. ...
New
mcass19
ExRatatui lets you cook up rich terminal UIs in Elixir, powered by Rust’s ratatui via Rustler NIFs. Build interactive terminal applicatio...
New
netoum
Corex is an accessible, unstyled UI component library for Phoenix that integrates Zag.js state machines using Vanilla JavaScript and Live...
New
Damirados
Hello everyone. After busy few months I am happy to announce v0.1.0 of Emerge &amp; Solve. They are GUI (Emerge) and State management (S...
New
ausimian
Emily is an Elixir library that runs Nx computations on Apple’s MLX. Install it as the default Nx backend and Nx, defn, Axon, Nx.Serving,...
New

We're in Beta

About us Mission Statement

Options

Thread Display Mode




Thread Preview

Skip Thread Previews