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
The obligatory hello world thread! Who are you and where are you from? :stuck_out_tongue:
4663 61218 595
New
cblavier
Hey there, It’s been more than a year since we started using LiveView as our main UI library and building a whole library of UI componen...
515 12931 101
New
wmnnd
Hey folks, I wanted to share with you a project I’ve been working on for a while: It’s an Open Source (AGPLv3) newsletter tool. Think Ma...
New
raa-ziq
Hi everyone :waving_hand: I wanted to share something I’ve been building — NowBlind, a random chat app designed to help people discover ...
New
sntran
In my third year of college, around 2010, I found Erlang. A few years later, I found Elixir. I liked the ideas at once: many small proces...
New
gtcode
I’ve been tinkering with Lynx (by José) via hold_ledger. I used AI to write the code, a separate specification, the tests, and the Lean p...
New
Ganna
Hi everyone, I have 8 years of production experience with Erlang/OTP and I’m just starting to get to know Elixir. What would you learn f...
New

Other Trending Topics Top

dominicletz
Hey there, I haven’t seen a list of useful Elixir specific skills for the popular AI tools yet so I’m starting one here with my first. ...
New
mudasobwa
I fully migrated to my own harness from Anthropic/Gemini and I think it’s time to share it. Welcome DSH, the DeepSeek Harness, fully writ...
New
KristerV
Hey. Is there anyone here who creates agents in their apps? Not talking about using agents, but creating them. I’m finding it pretty diff...
New
OndrejValenta
(I just needed to vent somewhere and LinkedIn is full of hope, or hype, I’m not sure which exactly) AI dream has many faces, but general...
New
kip
Localize is the next generation localisation library for Elixir. Think of it as ex_cldr version 3.0. The first version will be released ...
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

We're in Beta

About us Mission Statement

Options

Thread Display Mode




Thread Preview

Skip Thread Previews