Fl4m3Ph03n1x

Fl4m3Ph03n1x

Enable/disable a button in Phoenix 1.7 depending on state

Background

I have a button that may be disabled or not, depending on a set of conditions. I want to disable/enable the button without having to reload the page.

To achieve this I am using the following code:

my_app_live.ex

#provided as a sample
def disable_buttton? do
  if :rand.uniform(100) > 50 do
    "true"
  else
    "false"
  end
end

my_app.html.heex

<.button disabled={disable_button?)}>Execute Command</.button>

core_components.ex

  def button(assigns) do
    extra = assigns_to_attributes(assigns, [:disabled])

    assigns = assign(assigns, :disabled?, case Map.get(extra[:rest], :disabled) do
      "true" -> true
      _ -> false
    end)

    ~H"""
    <p><%= "INSIDE BUTTON: #{inspect(@disabled?)}" %></p>
    <button
      type={@type}
      class={if @disabled? do
      [
        "rounded-md bg-slate-400 px-3 py-2 text-sm font-semibold text-white shadow-sm",
        @class
      ]
    else
      [
        "rounded-md bg-indigo-600 px-3 py-2 text-sm font-semibold text-white shadow-sm",
        "active:text-white/80",
        @class
      ]
    end}
      {@rest}
    >
      <%= render_slot(@inner_block) %>
    </button>
    """
  end

Problem

For some reason, <p><%= "INSIDE BUTTON: #{inspect(@disabled?)}" %></p> always shows true and thus the button is always disabled.

In reality disable_buttton? may return true/false depending on which buttons are selected (if all forms have a value, then the button should be enabled), however I am unaware of any pattern to do this in Phoenix.

I am also not convinced I am using assigns properly.

Questions

  1. How can I enable/disable a button in Phoenix, depending on state?
  2. Am I using assigns_to_attributes and assign correctly in this sample?

I read Phoenix.Component — Phoenix LiveView v0.19.5 but I still don’t quite understand what I am missing here.

Marked As Solved

Fl4m3Ph03n1x

Fl4m3Ph03n1x

Issues found

The main reason my code didn’t work was because my disable_button? function was returning "false" instead of false. To be more precise:

So, in Phoenix LV, if the value is false the attribute disabled is removed from the node, while if it is any other thing (like "false"), the node gets the attribute as disabled=“something else”, which means that because disabled is still present, irrespective of value, it is considered as a disabled button.

This differs from the behaviour in the browser, where if I add disable="false" the browser will not consider the node disabled.

Source: Enable/disable a button in Phoenix 1.7 depending on state - #6 by Fl4m3Ph03n1x - Questions / Help - Elixir Programming Language Forum

Another issue is that this function also needs to return a value that depends on the state itself. In this case I am generating a random number, which is independent of state, thus the button would never update.

Answer

So, for those who are curious, this is the code I ended up with:

core_components.ex

This is my modified button function:

  @doc """
  Renders a button.

  ## Examples

      <.button>Send!</.button>
      <.button phx-click="go" class="ml-2" disabled=false>Send!</.button>
  """
  attr :type, :string, default: nil
  attr :class, :string, default: nil
  attr :disabled, :boolean, default: false
  attr :rest, :global, include: ~w(form name value)

  slot :inner_block, required: true

  def button(assigns) do
    ~H"""
    <button
      type={@type}
      class={if @disabled do
      [
        "rounded-md bg-slate-400 px-3 py-2 text-sm font-semibold text-white shadow-sm",
        @class
      ]
    else
      [
        "phx-submit-loading:opacity-75 rounded-md bg-indigo-600 px-3 py-2 text-sm font-semibold text-white shadow-sm",
        "hover:bg-indigo-500 active:text-white/80",
        @class
      ]
    end}
      {@rest}
      disabled={@disabled}
    >
      <%= render_slot(@inner_block) %>
    </button>
    """
  end

And here is how I use it:

my_app_live.html.heex

<.button class="min-w-full" disabled={disable_button?(@param1, @state)}>Execute Command</.button>

This depends on the state, because the state changes with time, which means my button’s appearance will also change with time!

Where Next?

Popular Frontend topics Top

Zuber
How to make a website like webnovel and wattpadd where subscribers and logged in user post stories like their own Novel in a website and ...
New
pillaiindu
I mean, when you render all the HTML at the server side and the data is sent through HTTP requests, except only if some tiny things are d...
New
sona11
What is the difference between tuple relational calculus (TRC) and domain relational calculus (DRC)? What distinguishes them from relatio...
New
prego4444
how can i make a border like this to be exactly on the midle of the edge? i could only found border in inside and outside but nothing on ...
New
Fl4m3Ph03n1x
Background I have a fresh umbrella app and I am trying to create a Phoenix app inside it. However, even though I can create the Phoenix a...
New
JessicaW33
Hello everyone, I’m working on optimizing the performance of React Native applications and would like to gather insights and suggestions...
New
Fl4m3Ph03n1x
Background I have Phoenix umbrella application. When inside said application, I can run it without issues if MIX_ENV=prod. However, if I ...
New
gameengineer
We are developing on Samsung Tab Active 4 Pro using Android Studio, kotlin and java. We are getting what we think are app deadlocks. The ...
New
Clintonsuck
Hello, I am new and trying to build my first app. So far, everything was going okay, but now I’m stuck and don’t know how to proceed. May...
New
ounce591
I am currently designing the navbar of a workout tracking app written using React Native. The navbar has three buttons: Splits/Plans ...
New

Other popular topics Top

Devtalk
Hello Devtalk World! Please let us know a little about who you are and where you’re from :nerd_face:
New
Rainer
My first contact with Erlang was about 2 years ago when I used RabbitMQ, which is written in Erlang, for my job. This made me curious and...
New
AstonJ
Just done a fresh install of macOS Big Sur and on installing Erlang I am getting: asdf install erlang 23.1.2 Configure failed. checking ...
New
PragmaticBookshelf
Build efficient applications that exploit the unique benefits of a pure functional language, learning from an engineer who uses Haskell t...
New
New
PragmaticBookshelf
25 puzzles that will make you a better C programmer by challenging your knowledge of the language, and explaining the technical details o...
New
First poster: AstonJ
Jan | Rethink the Computer. Jan turns your computer into an AI machine by running LLMs locally on your computer. It’s a privacy-focus, l...
New
CommunityNews
A Brief Review of the Minisforum V3 AMD Tablet. Update: I have created an awesome-minisforum-v3 GitHub repository to list information fo...
New
sir.laksmana_wenk
I’m able to do the “artistic” part of game-development; character designing/modeling, music, environment modeling, etc. However, I don’t...
New
mindriot
Ok, well here are some thoughts and opinions on some of the ergonomic keyboards I have, I guess like mini review of each that I use enoug...
New