paulofabiano

paulofabiano

State Machine: current state's path

Hey, guys!

I implemented a state machine with Machinery to control the UI sequence I show to my user. But I have a problem.

When I am in the :ready state, I show a live_component A with Card. This card contains a question and possible answers. If the user selects the answer 1, I change the state to, let’s say “A1” and I show the next live_component B. If the user selects answer 2, I change to “A2” and show the next component C.

So far so good. This is a very basic transition and everything is working well. In my LiveView each live_component is wrapper within a condition like:

if state == “ready” do live_component A end
if state == “A1” do live_component B end
if state == “A2” do live_component C end

What’s the problem? Each live_component is shown one below the other.
So, when I transit to state “A1”, the live_component A is hidden.

So, I needed some way to construct a breadcrumb of the current state, from the initial one until the current state, like: path => [“ready”, “A1”, “B2”, “C1”]

This way, I could have:

if Enum.member?(path, “ready”) do live_component A end ← visible
if Enum.member?(path, “A1”) do live_component B end ← visible
if Enum.member?(path, “A2”) do live_component C end
if Enum.member?(path, “B1”) do live_component D end
if Enum.member?(path, “B2”) do live_component E end ← visible
if Enum.member?(path, “C1”) do live_component F end ← visible
if Enum.member?(path, “C2”) do live_component F end

I thought about using Machinery’s log_transition to manage by my own this new path property. Basically, it would be keeping and appending a new state at the end of the path list.

So, I’d like your opinion about this approach. Not sure if it is the nicest one. I’ve been researching also about the Zipper list/tree and some implementations seem to keep this path as we navigate the tree.

First Post!

APB9785

APB9785

Creator of ECSx

Maybe instead of having just one state, use multiple assigns like:

def mount(_params, _session, socket) do
  socket = assign(socket, choice_A: nil, choice_B: nil, choice_C: nil)
  {:ok, socket}
end

Then when a choice is made,

assign(socket, choice_A: 1)
# or
assign(socket, choice_A: 2)

and in the html.leex

<%= live_component @socket, LiveComponentA %>

<%= if @choice_A == 1 do %>
  <%= live_component @socket, LiveComponentB %>
<% end%>
<%= if @choice_A == 2 do %>
  <%= live_component @socket, LiveComponentC %>
<% end%>

<%= if @choice_B == 1 do %>
  <%= live_component @socket, LiveComponentD %>
<% end %>
<%= if @choice_B == 2 do %>
  <%= live_component @socket, LiveComponentE %>
<% end %>

etc…

Where Next?

Popular in Questions Top

9mm
I am constructing a JSON object (map) and I need to conditionally set a field. I’m trying to write proper elixir-way code… and I’m at a l...
New
qwerescape
Is there a way to get the call stack or stack trace at any point in the code? Not from exceptions, but an expression that returns how the...
New
albydarned
Hello all! I am typing this post from my new MacBook Pro with the M1 chip. I’m loving it so far, and will probably use it as my daily dr...
New
earth10
Hi, I’m just starting to build a side-project with Elixir and Phoenix and doing some basic test with Elixir alone. What strikes me is th...
New
chrisalley
ExUnit now has describe blocks which is a welcome addition coming from RSpec. In the docs, it states that nested hierarchies of describe ...
New
lessless
I believe there are people here who are dealing with CSV files import on the daily basis, and since Excel is a really popular tool there ...
New
JeremM34
Hello, how can I check the Phoenix version ? Thanks !
New
vegabook
I'm brand new to Phoenix and I have stripped one of the demo applications to the bone. I just want to get an svg up on the screen. Here i...
New
ashish173
I am using Ecto timestamps with postgres, I can see the timestamps() use the :naive_dateime but for my use case I wanted to store the ti...
New
sergio_101
I am VERY much an elixir newbie. I have taken one elixir course and one phoenix course on Udemy. During that course, I saw the instructor...
New

Other popular topics Top

9mm
I am constructing a JSON object (map) and I need to conditionally set a field. I’m trying to write proper elixir-way code… and I’m at a l...
New
mcarvalho
What is the difference between System.get_env and Application.get_env? For example, what are best practices to use one versus another.
New
chrismccord
Phoenix 1.4.0 released Phoenix 1.4 is out! This release ships with exciting new features, most notably with HTTP2 support, improved deve...
688 30840 112
New
JorisKok
I have a server on AWS, and was running a load test using artillery. When looking at the Phoenix dashboard I see the Ports going to 100% ...
New
josevalim
Hi everyone, One of the features added to Elixir early on to help integration with Erlang code was the idea of overridable function defi...
New
aalberti333
As the title describes, I’m trying to run Enum.map() over a list of key/value pairs, where the value is a map. My data looks like this: ...
New
jerry
Good day to you all. I have been struggling to get a query involving like and ilike to work. Can anyone assist me on this, please? pro...
New
freewebwithme
Using vs code and installed ElixirLS: support and debugger. And I got an error popped up on start up says Failed to run ‘elixir’ comma...
New
nsuchy
Hi. I’ve noticed that Windows Powershell has it’s own IEX command and you cannot access Elixir’s IEX due to the conflict. This isn’t a cr...
New
jononomo
For some reason my phoenix channels are working for me in my local dev environment, but as soon as I deploy via Docker, I get a 403 error...
New

We're in Beta

About us Mission Statement