that’s kind of worked but had to dealt with a lot of bugs around, one left I guess 
for helping other people, I’d like to share whole codes and also ask a few things about Elixir, I think I’m not getting benefits of functional programming what I do in “add” event.
first I got rid of the modal popup, one have a single page. Here’s a gif for the latest the version.

When I click on I remove it crashes due to value
is nil.
Here’s html part of remove
button, and yes when I check html I can see phx-value
is set correctly.
<%= for item <- @cart_items do %>
<tr>
<td><%= item.name %></td>
<td><%= item.price %></td>
<td><%= item.count %></td>
<td>
<button type="button" phx-click="remove" phx-value="<%= item.product_id %>">-</button>
</td>
</tr>
<% end %>
and here’s the log of remove
action (during screen recording)
%{count: 1, id: 1, name: "Water", price: "12.5 TRY", product_id: 1}
%{count: 2, id: 2, name: "Water", price: "12.5 TRY", product_id: 1}
%{count: 3, id: 2, name: "Water", price: "12.5 TRY", product_id: 1}
%{count: 4, id: 2, name: "Water", price: "12.5 TRY", product_id: 1}
%{count: 18, id: 2, name: "Water", price: "12.5 TRY", product_id: 1}
%{count: 3, id: 2, name: "Milk", price: "20.0 TRY", product_id: 2}
%{count: 6, id: 3, name: "Milk", price: "20.0 TRY", product_id: 2}
%{count: 7, id: 3, name: "Milk", price: "20.0 TRY", product_id: 2}
%{count: 8, id: 3, name: "Milk", price: "20.0 TRY", product_id: 2}
%{count: 9, id: 3, name: "Milk", price: "20.0 TRY", product_id: 2}
%{count: 30, id: 3, name: "Juice", price: "20.0 TRY", product_id: 3}
%{count: 60, id: 4, name: "Juice", price: "20.0 TRY", product_id: 3}
%{count: 90, id: 4, name: "Juice", price: "20.0 TRY", product_id: 3}
%{count: 120, id: 4, name: "Juice", price: "20.0 TRY", product_id: 3}
%{count: 150, id: 4, name: "Juice", price: "20.0 TRY", product_id: 3}
++++ removing ++++
""
%{"value" => ""}
++++ removed ++++
value
is empty?
backend-code:
@impl true
def handle_event("remove", params, socket) do
%{"value" => value} = params
IO.puts("++++ removing ++++")
IO.inspect(value)
IO.inspect(params)
IO.puts("++++ removed ++++")
request = params["request"]
product_id = to_integer(request["value"])
cart_items = socket.assigns.cart_items
existing_product = Enum.find(socket.assigns.products, fn p -> p.id == product_id end)
cart_items = List.delete(cart_items, existing_product)
socket = assign(socket, :cart_items, cart_items)
{:noreply, socket}
end
Whole Source Code:
lib/myapp_web/live/admin/index.html.leex
<section class="row">
<article class="column order-form">
<h2> Order Request </h2>
<%= f = form_for @changeset, "#",
id: "order-request-form",
phx_change: "change",
phx_submit: "save" %>
<%= label f, :phone_number %>
<%= text_input f, :phone_number, value: @phone_number %>
<%= error_tag f, :phone_number %>
<h2>Avaliable Products</h2>
<table>
<thead>
<tr>
<th>Name</th>
<th>Count</th>
<th></th>
</tr>
</thead>
<tbody id="products">
<tr>
<td>
<%= select f, :product_id, Enum.map(@products, &{&1.name, &1.id }), selected: @add_product_id %>
</td>
<td>
<%= select f, :count, 1..50, selected: @add_count %>
<%= error_tag f, :count %>
</td>
<td>
<button type="button" phx-click="add"
phx-value-product-id="<%= @add_product_id %>"
phx-value-count="<%= @add_count %>">+</button>
</td>
</tr>
</tbody>
</table>
<h2>Cart</h2>
<table id="cart">
<thead>
<tr>
<th>Name</th>
<th>Price</th>
<th>Count</th>
<th></th>
</tr>
</thead>
<tbody>
<%= if @cart_items do %>
<%= for item <- @cart_items do %>
<tr>
<td><%= item.name %></td>
<td><%= item.price %></td>
<td><%= item.count %></td>
<td>
<button type="button" phx-click="remove" phx-value="<%= item.product_id %>">-</button>
</td>
</tr>
<% end %>
<% else %>
<tr>
<td colspan="4"> No Item added yet </td>
</tr
<% end %>
</tbody>
</table>
<%= submit "Save", phx_disable_with: "Saving..." %>
</form>
</article>
</section>
<section class="row">
<article class="column">
<h2> Pending Orders </h2>
<table class="pending-orders">
<thead>
<th>Order ID</th>
<th>Order Date</th>
<th style="text-align:center">Actions</th>
</thead>
<tbody>
<%= for order <- @pending_orders do %>
<tr id="order-<%= order.id %>">
<td><%= order.id %></td>
<td><%= order.inserted_at %></td>
<td>
<button>Delivered</button>
<button>Cancelled</button>
</td>
</tr>
<% end %>
</tbody>
</table>
</article>
</section>
lib/myapp_web/live/admin/index.ex
defmodule MyAppWeb.AdminLive.Index do
use MyAppWeb, :live_view
alias MyAppWeb.{Products, Orders}
@impl true
def mount(_params, _session, socket) do
changeset = Orders.Request.changeset(%Orders.Request{}, %{})
socket =
socket
|> assign(:pending_orders, load_pending_orders())
|> assign(:changeset, changeset)
|> assign(:order_request, nil)
|> assign(:products, load_avaliable_products())
|> assign(:add_product_id, nil)
|> assign(:add_count, 0)
|> assign(:cart_items, nil)
|> assign(:phone_number, nil)
|> assign(:cart_items, nil)
{:ok, socket}
end
@impl true
def handle_params(params, _url, socket) do
{:noreply, apply_action(socket, socket.assigns.live_action, params)}
end
@impl true
def handle_event("change", params, socket) do
request = params["request"]
socket =
socket
|> assign(:phone_number, request["phone_number"])
|> assign(:add_product_id, request["product_id"])
|> assign(:add_count, request["count"])
|> assign(:cart_items, socket.assigns.cart_items)
{:noreply, socket}
end
@impl true
def handle_event("save", _params, socket) do
# not implemented yet
{:noreply, socket}
end
@impl true
def handle_event("add", params, socket) do
%{"count" => count, "product-id" => product_id, "value" => _value} = params
product_id = to_integer(product_id)
count = to_integer(count)
cart_items = socket.assigns.cart_items
product = Enum.find(socket.assigns.products, fn p -> p.id == product_id end)
id = if cart_items == nil, do: 1, else: Enum.count(cart_items) + 1
order_item = %{
:id => id,
:product_id => product_id,
:name => product.name,
:count => count,
:price => "#{product.price} #{product.currency}"
}
cart_items =
if cart_items == nil do
[order_item]
else
cart_items = if existing_product = Enum.find(cart_items, fn i -> i.product_id == product_id end) do
IO.inspect(existing_product)
new_count = existing_product.count + count
cart_items = List.delete(cart_items, existing_product)
order_item = %{order_item | count: new_count}
[cart_items] ++ [order_item]
else
[cart_items] ++ [order_item]
end
cart_items
end
socket = socket |> assign(:cart_items, List.flatten(cart_items))
{:noreply, socket}
end
@impl true
def handle_event("remove", params, socket) do
%{"value" => value} = params
IO.puts("++++ removing ++++")
IO.inspect(value)
IO.inspect(params)
IO.puts("++++ removed ++++")
request = params["request"]
product_id = to_integer(request["value"])
cart_items = socket.assigns.cart_items
existing_product = Enum.find(socket.assigns.products, fn p -> p.id == product_id end)
cart_items = List.delete(cart_items, existing_product)
socket = assign(socket, :cart_items, cart_items)
{:noreply, socket}
end
defp apply_action(socket, :index, _params) do
socket
|> assign(:page_title, "Admin")
|> assign(:pending_orders, load_pending_orders())
end
def format_product_name(product) do
"#{product.name} - #{product.price} #{product.currency}"
end
defp load_pending_orders do
Orders.list_pending_orders()
end
defp load_avaliable_products do
Products.list_avaliable_products()
end
defp to_integer(s) do
{i, _s} = Integer.parse(s)
i
end
end
PS: It didn’t work with temporary_assigns
like in the first initial.