Fl4m3Ph03n1x

Fl4m3Ph03n1x

Assigns is not assigning attribute in custom core component

Background

I have a custom component in my LiveView, which is basically a group of checkboxes.
I want to add a new attribute to my custom component, however no matter what I do, I always get nil when accessing said attribute.

Code

core_components.ex

  @doc """
  Generate a checkbox group for multi-select.

  ## Examples

    <.checkgroup
      field={@form[:genres]}
      label="Genres"
      options={[{"Fantasy", "fantasy"}, {"Science Fiction", "sci-fi"}]}
      selected={[{"Fantasy", "fantasy"}]}
    />

  """
  attr :id, :any
  attr :name, :any
  attr :label, :string, default: nil
  attr :field, Phoenix.HTML.FormField, doc: "a form field struct retrieved from the form, for example: @form[:genres]"
  attr :errors, :list
  attr :required, :boolean, default: false
  attr :rest, :global, include: ~w(form readonly)
  attr :class, :string, default: nil
  attr :options, :list, default: [], doc: "the options to pass to Phoenix.HTML.Form.options_for_select/2"
  attr :selected, :list, default: [], doc: "the currently selected options, to know which boxes are checked"

  attr :meow, :any, default: "meow", doc: "a very cool new attribute!"

  def checkgroup(assigns) do
    new_assigns =
      assigns
      |> assign(:multiple, true)
      |> assign(:type, "checkgroup")

    input(new_assigns)
  end


  def input(%{type: "checkgroup"} = assigns) do
    ~H"""
    <p> <%= "Cat says: #{@meow}" %></p> 

    <div class="mt-2">
      <%= for opt <- @options do %>
        <div class="relative flex gap-x-3">
          <div class="flex h-6 items-center">
            <input id={opt.id} name={@name} type="checkbox" value={opt.id} checked={opt in @selected} disabled={false} />
          </div>
          <div class="text-sm leading-6">
            <label  for={opt.id} ><%= opt.name %></label>
          </div>
        </div>

      <% end %>
    </div>
    """
  end

Here I am using a customer component to render a stylish checkbox group. It works fine, except for the :meow attribute, which somehow is always nil when inside the input function.

Error

Using this code as a sample:

<.checkgroup field={@form[:my_form]} label="SUper question!" options={@sounds} selected={@selected_sounds} meow={[1, 2]} required />

I get the following error upon rendering this code:

** (exit) an exception was raised:
    ** (KeyError) key :meow not found in: %{
  __changed__: nil,
  __given__: %{
    __changed__: nil,
    __given__: %{
      __changed__: nil,
      __given__: %{
        __changed__: nil,
        field: %Phoenix.HTML.FormField{
          id: "my_form",
          name: "my_form",
          errors: [],
          field: :my_form,
          form: %Phoenix.HTML.Form{
            source: %{"some_command" => []},
            impl: Phoenix.HTML.FormData.Map,
            id: nil,
            name: nil,
            data: %{},
            hidden: [],
            params: %{"some_command" => []},
            errors: [],
            options: [],
            index: nil,
            action: nil
          },
          value: nil
        },
        label: "SUper question!",
        meow: [1, 2],
        options: [1, 2, 3, 4],
        # .... more things follow

As you can see, meow: [1, 2], is clearly present. Yet, @meow returns nil and using assigns.meow outright crashes the application.

What am I doing wrong here and how can I fix it?

Marked As Solved

Fl4m3Ph03n1x

Fl4m3Ph03n1x

After a lot of digging around, i realized that all of the input functions deal with assigns. This meant that some things are being done that I dont fully understand, not control.

I decided to move away from using/modifying the input functions and created my own component from scratch:

@doc """
  Generate a checkbox group for multi-select.

  ## Examples

    <.checkgroup
      field={@form[:genres]}
      label="Genres"
      options={[{"Fantasy", "fantasy"}, {"Science Fiction", "sci-fi"}]}
      selected={[{"Fantasy", "fantasy"}]}
    />

  """
  attr :name, :any

  attr :field, Phoenix.HTML.FormField,
    doc: "a form field struct retrieved from the form, for example: @form[:genres]"

  attr :required, :boolean, default: false

  attr :options, :list,
    default: [],
    doc: "the options to pass to Phoenix.HTML.Form.options_for_select/2"

  attr :disabled, :list, default: [], doc: "the list of options that are disabled"

  attr :selected, :list,
    default: [],
    doc: "the currently selected options, to know which boxes are checked"

  def checkgroup(%{field: %Phoenix.HTML.FormField{} = field} = assigns) do
    assigns =
      assigns
      |> assign(:name, "#{field.name}[]")

    ~H"""
    <div class="mt-2">
      <%= for opt <- @options do %>
        <div class="relative flex gap-x-3">
          <div class="flex h-6 items-center">
            <input
              id={opt.id}
              name={@name}
              type="checkbox"
              value={opt.id}
              class={
                if opt in @disabled do
                  "h-4 w-4 rounded border-gray-300 text-gray-300 focus:ring-indigo-600"
                else
                  "h-4 w-4 rounded border-gray-300 text-indigo-600 focus:ring-indigo-600"
                end
              }
              checked={opt in @selected}
              disabled={opt in @disabled}
            />
          </div>
          <div class="text-sm leading-6">
            <label
              for={opt.id}
              class={
                if opt in @disabled do
                  "text-base font-semibold text-gray-300"
                else
                  "text-base font-semibold text-gray-900"
                end
              }
            >
              <%= opt.name %>
            </label>
          </div>
        </div>
      <% end %>
    </div>
    """
  end

which works as expected and all the assigns not have the expected values.

Also Liked

sodapopcan

sodapopcan

Crap, sorry, I was working on a response to this a few days ago and got distracted :grimacing: Sorry about that! Glad you solved it!

Where Next?

Popular in Questions Top

siddhant3030
Hi, I have to write a raw query for one of my project. But till now I have used ecto queries and don’t have much experience writing raw ...
New
minhajuddin
I have seen a lot of code which picks the first element from a list using Enum.at(0) instead of List.first. Is there a reason why people ...
New
LegitStack
I’m trying to make a websocket server in Phoenix or raw Elixir. I heard about gun, I think I could use cowboy, but since I’m not that sma...
New
stefanluptak
Hello everybody, usually, I use a 29" ultra-wide monitor for VSCode which can easily accomodate explorer (files panel) + file with code ...
New
RisingFromAshes
I’ve read in another post that it may be possible with a router helper - but I couldn’t find an appropriate one, and tbh, I’m still just ...
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
jason.o
In the code below, if the create action is not set to accept “extra_key” as an input, it errors out with a message shown above. Is there ...
New
WestKeys
Currently suffering from paralysis by [HTTP client] analysis. This is rather unusual in Elixirland as there tends to be consensus on the ...
New
openscript
Hello! Sorry for this astonishing simple question, but I’m really stuck. I try to set up the intellij-elixir plugin, but I don’t know ho...
New
lanycrost
Hi everyone! I need implement if…else if…else condition from my elixir code, and anymore of this control flow structures not work proper...
New

Other popular topics Top

vertexbuffer
Hello, can anybody help here..? I have a list of players and I what to delete an element, but every for loop the list is reverting to ori...
New
siddhant3030
Hi, I have to write a raw query for one of my project. But till now I have used ecto queries and don’t have much experience writing raw ...
New
skosch
To my knowledge, put_in, Map.update etc. all have the one limitation of not automatically creating intermediate keys when needed (for exa...
New
Nvim
Anybody knows a comprehensive comparison of Django and Phoenix, thanks for the help. Where are they similar? Where do they differ the m...
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
gshaw
What is the idiomatic way of matching for not nil in Elixir? E.g., First way: defp halt_if_not_signed_in(conn, signed_in_account) when...
New
aesmail
Hello guys, I have finally made it. I created an admin interface for a framework. It’s been on my todo list for years and with the curre...
New
romenigld
I am trying to run a deploy with docker and I successfully runned with this command: docker build -t romenigld/blog-prod . but when I t...
New
marick
I had some trouble figuring out how to make many-to-many associations work. Once I got it working, I wrote a blog post. Because I’m a nov...
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