ParamsMap

A utility module for working with Phoenix and LiveView parameters that are typically string-keyed, but can be accessed and updated using atom keys.

The Problem

Phoenix and LiveView params arrive as string-keyed maps (e.g. %{"name" => "Alice", "email" => "alice@example.com"}). When building forms or handling assigns, atom keys often feel more natural. Manually converting between key types is tedious and error-prone.

The Solution

ParamsMap provides Map-compatible functions that accept atom keys and automatically use the correct key type based on the existing params structure. Write :name and it works with both %{name: "Alice"} and %{"name" => "Alice"}.

Installation

Add params_map to your list of dependencies in mix.exs:

def deps do
  [
    {:params_map, "~> 0.0"}
  ]
end

Usage

Get

ParamsMap.get(%{"name" => "Alice"}, :name)           # => "Alice"
ParamsMap.get(%{name: "Alice"}, :name)               # => "Alice"
ParamsMap.get(%{"email" => "a@b.com"}, :name, "N/A") # => "N/A"

Put & Put New

ParamsMap.put(%{"a" => 1}, :b, 2)  # => %{"a" => 1, "b" => 2}
ParamsMap.put(%{a: 1}, :b, 2)      # => %{a: 1, b: 2}
ParamsMap.put_new(params, :id, id) # Only sets if key is missing

Update

ParamsMap.update(%{"count" => 1}, :count, 0, &(&1 + 1))  # => %{"count" => 2}
ParamsMap.update(%{count: 5}, :count, 0, &(&1 + 1))      # => %{count: 6}

Merge

merge/2 handles maps with mixed key types by converting one side to match the other:

ParamsMap.merge(%{"a" => 1}, %{b: 2})   # => %{"a" => 1, "b" => 2}
ParamsMap.merge(%{a: 1}, %{"b" => 2})   # => %{a: 1, b: 2}
ParamsMap.merge(%{a: 1}, %{b: 2})       # => %{a: 1, b: 2}

Take

Extract specific keys, using atom keys for lookups:

ParamsMap.take(%{"name" => "Alice", "email" => "a@b.com"}, [:name])
# => %{"name" => "Alice"}

Clean Embeds

Phoenix form params for nested embeds use map syntax with numeric string keys (%{"0" => %{...}, "1" => %{...}}). clean_embeds/1 converts these to lists for Ecto:

ParamsMap.clean_embeds(%{
  "items" => %{
    "0" => %{"name" => "Item 1"},
    "1" => %{"name" => "Item 2"}
  }
})
# => %{
#   "items" => [
#     %{"name" => "Item 1"},
#     %{"name" => "Item 2"}
#   ]
# }

License

MIT