bilalhassankh
Need help with form fields
Create new project–>when user select a company and select it’s contact , after that if user change the company, it should shows blank contact filed for change company, and should not save the previous contact of company
I want to remove the selection from contacts and buildings when selecting other company contact. What will be the solution?
form_component.html.heex
<div class="contacts_newcom_m">
<h1><%= page_title(@action) %></h1>
<div class="a_asside_account_c_first_ss mt-20">
<.form let={f} for={@changeset} phx-target={@myself} phx-change="validate" phx-submit="save" phx-update="replace">
<span>
<%= if entry = List.first(@uploads.image.entries) do%>
<%= live_img_preview entry %>
<% else %>
<%= if @project.project_image do%>
<img src={@project.project_image}/>
<% else %>
<img src={Routes.static_path(@socket, System.get_env("DEFAULT_AVATAR"))} alt="img"/>
<% end %>
<% end %>
<span class="account_add_img" phx-drop-target={@uploads.image.ref} onclick={"document.getElementById('#{@uploads.image.ref}').click()"}>
<img src={Routes.static_path(@socket, "/images/Frame 811261 (1).svg")} alt=""/>
<%= gettext("add image") %>
<%= live_file_input @uploads.image, hidden: true %>
<%= if entry = List.first(@uploads.image.entries) do%>
<%= for err <- upload_errors(@uploads.image, entry) do %>
<span><%= image_errors(err) %></span>
<% end %>
<% end %>
</span>
</span>
<div class="form-control">
<p><%= gettext("name") %></p>
<%= text_input f, :name %>
<%= error_tag f, :name %>
</div>
<div class="form-control ">
<p><%= gettext("description") %></p>
<%= text_input f, :description %>
<%= error_tag f, :description %>
</div>
<div class="form-control ">
<p><%= gettext("Estimated Time") %></p>
<%= text_input f, :estimated_time, type: "number", min: 0, oninput: "this.value = Math.abs(this.value)" %>
<%= error_tag f, :estimated_time %>
</div>
<div class="form-control ">
<p><%= gettext("Project Start Date") %></p>
<%= datetime_local_input f, :project_start_date %>
<%= error_tag f, :project_start_date %>
</div>
<div class="form-control ">
<p><%= gettext("Company Contact") %></p>
<%= select f, :company_contact_id, @company_contacts_options, options(:company_contact, assigns[:parent]) %>
<%= error_tag f, :company_contact_id %>
</div>
<%= inputs_for f, :project_contacts, fn a -> %>
<%= hidden_input a, :contact_id %>
<%= hidden_input a, :company_id %>
<% end %>
<%= inputs_for f, :project_buildings, fn a -> %>
<%= hidden_input a, :building_id %>
<%= hidden_input a, :company_id %>
<% end %>
<%= hidden_input f, :stage, value: "pending" %>
<%= error_tag f, :stage %>
<%= hidden_input f, :lead_column_id %>
<%= error_tag f, :lead_column_id %>
<%= hidden_input f, :company_id, value: @current_user.company_id %>
<%= error_tag f, :company_id %>
<div class="form-control ">
<p><%= gettext("Contacts") %></p>
<%= live_component AppeoWeb.TagDropdown,
id: :project_contacts,
ex_tags: @ex_contact_taggings,
module: %{name: __MODULE__, id: @id, field: :contact_id},
tags: @contact_options,
disabled: options(:contact, assigns[:parent])
%>
<%= error_tag f, :project_contacts %>
</div>
<div class="form-control">
<p><%= gettext("Buildings") %></p>
<%= live_component AppeoWeb.TagDropdown,
id: :project_buildings,
ex_tags: @ex_building_taggings,
module: %{name: __MODULE__, id: @id, field: :building_id},
tags: @building_options
%>
<%= error_tag f, :project_buildings %>
</div>
<div class="form-control ">
<p><%= gettext("Project Type") %></p>
<%= select f, :project_type, ["Roofing": "roofing", "Any Name": "any name"] %>
<%= error_tag f, :project_type %>
</div>
<div class="form-control ">
<button class="btn" type="submit"><%= gettext("save") %></button>
<div class="btn"><%= live_patch gettext("Cancel"), to: @return_to %></div>
</div>
</.form>
</div>
</div>
defmodule AppeoWeb.LeadsLive.FormComponent do
use AppeoWeb, :live_component
alias Appeo.Leads
alias Appeo.Leads.Project
alias Appeo.Contacts
alias Ecto.Changeset
alias Appeo.ProjectPermissions
@bucket_dir_name "projects"
@impl true
def update(%{current_user: _, project: project} = assigns, socket) do
params = default_params(project.id, assigns)
changeset = Leads.change_project(project, params)
company_contacts = Contacts.list_company_contacts_for_project()
company_contacts_options = Enum.map(company_contacts, &{&1.name, &1.id})
company_contact_id =
project.company_contact_id ||
company_contacts
|> Enum.at(0, %{})
|> Map.get(:id, "")
company_contact_id = to_string(company_contact_id)
building_options = building_options(company_contact_id, company_contacts)
contact_options = contacts_options(company_contact_id, company_contacts)
{ex_contact_taggings, ex_building_taggings} =
if project.id do
building_tags = Map.new(building_options, &{&1.id, &1})
contact_tags = Map.new(contact_options, &{&1.id, &1})
{
Enum.map(project.project_contacts, &Map.get(contact_tags, &1.contact_id)),
Enum.map(project.project_buildings, &Map.get(building_tags, &1.building_id))
}
else
{[], []}
end
socket =
socket
|> assign(assigns)
|> assign(:changeset, changeset)
|> assign(:project, project)
|> assign(:contact_options, contact_options)
|> assign(:building_options, building_options)
|> assign(:company_contacts_options, company_contacts_options)
|> assign(:company_contacts, company_contacts)
|> assign(:uploaded_files, [])
|> assign(:ex_contact_taggings, ex_contact_taggings)
|> assign(:ex_building_taggings, ex_building_taggings)
|> allow_upload(:image,
accept: ~w(.jpg .jpeg .png),
max_entries: 1,
max_file_size: 3_145_726
)
{:ok, socket}
end
def update(assigns, socket) do
socket =
case assigns do
%{field: :contact_id, taggings: taggings} ->
changeset = build_changeset(:contact_id, taggings, socket.assigns)
assign(socket, changeset: changeset, ex_contact_taggings: taggings)
%{field: :building_id, taggings: taggings} ->
changeset = build_changeset(:building_id, taggings, socket.assigns)
assign(socket, changeset: changeset, ex_building_taggings: taggings)
end
{:ok, socket}
end
@impl true
def handle_event("validate", %{"project" => project}, socket) do
changeset =
socket.assigns.project
|> Leads.change_project(project)
|> Map.put(:action, :validate)
company_contacts = socket.assigns.company_contacts
contacts_options = contacts_options(project["company_contact_id"] || "", company_contacts)
building_options = building_options(project["company_contact_id"] || "", company_contacts)
socket =
socket
|> assign(:contact_options, contacts_options)
|> assign(:building_options, building_options)
{:noreply, assign(socket, :changeset, changeset)}
end
def handle_event("save", %{"project" => project_params}, socket) do
socket
|> upload_image(@bucket_dir_name)
|> save_project(socket, socket.assigns.action, project_params)
end
def handle_event("project_contact", %{"index" => index}, socket) do
changeset = socket.assigns.changeset
project_contacts = remove_field(changeset.changes.project_contacts, index)
changeset = put_in(changeset.changes.project_contacts, project_contacts)
{:noreply, assign(socket, :changeset, changeset)}
end
def build_changeset(:contact_id, taggings, assigns) do
company_id = assigns.current_user.company_id
project_contacts = Enum.map(taggings, &%{company_id: company_id, contact_id: &1.id})
assigns.changeset
|> Changeset.put_assoc(:project_contacts, project_contacts)
|> Changeset.apply_changes()
|> Project.changeset()
|> Map.put(:action, :validate)
end
def build_changeset(:building_id, taggings, assigns) do
company_id = assigns.current_user.company_id
project_buildings = Enum.map(taggings, &%{company_id: company_id, building_id: &1.id})
assigns.changeset
|> Changeset.put_assoc(:project_buildings, project_buildings)
|> Changeset.apply_changes()
|> Project.changeset()
|> Map.put(:action, :validate)
end
defp save_project({:error, error}, socket, _, _) do
{:noreply, put_flash(socket, :error, error)}
end
defp save_project({:ok, path}, socket, :edit_project, project_params) do
path = path || socket.assigns.project.project_image
project_params = Map.put(project_params, "project_image", path)
case Leads.update_project(socket.assigns.project, project_params) do
{:ok, _contact} ->
{:noreply,
socket
|> put_flash(:info, gettext("Project updated successfully"))
|> push_patch(to: socket.assigns.return_to)}
{:error, %Ecto.Changeset{} = changeset} ->
{:noreply, assign(socket, :changeset, changeset)}
end
end
defp save_project({:ok, path}, socket, :new_project, project_params) do
project_params =
project_params
|> Map.put("project_image", path)
|> Map.put(
"project_permission_joined_users",
[
%{
"company_id" => socket.assigns.current_user.company_id,
"user_id" => socket.assigns.current_user.id,
"project_permission_id" => ProjectPermissions.get_permission_with_name("Owner").id
}
]
)
case Leads.create_project(project_params) do
{:ok, _project} ->
{:noreply,
socket
|> put_flash(:info, gettext("Project created successfully"))
|> push_redirect(to: socket.assigns.return_to)}
{:error, %Ecto.Changeset{} = changeset} ->
{:noreply, assign(socket, changeset: changeset)}
end
end
defp default_params(nil, %{current_user: current_user} = assigns) do
%{
lead_column_id: assigns.lead_column_id,
company_id: current_user.company_id
}
end
defp default_params(_, _assigns), do: %{}
defp contacts_options("", _assigns), do: []
defp contacts_options(company_contact_id, company_contacts) do
company_contacts
|> Enum.find(&(to_string(&1.id) == company_contact_id))
|> Map.get(:contacts)
|> Enum.map(&%{name: &1.first_name, id: &1.id})
end
defp building_options("", _assigns), do: []
defp building_options(company_contact_id, company_contacts) do
company_contacts
|> Enum.find(&(to_string(&1.id) == company_contact_id))
|> Map.get(:buildings)
|> Enum.map(&%{name: &1.building_name, id: &1.id})
end
defp remove_field(changeset_list, index) do
changeset_list
|> Enum.with_index()
|> Enum.reduce([], fn {value, i}, acc -> if "#{i}" == index, do: acc, else: acc ++ [value] end)
end
defp page_title(:new_project), do: gettext("Create New Project")
defp page_title(:edit_project), do: gettext("Update Project")
defp options(:company_contact, [:contact, contact]),
do: buid_options(contact.company_contact_id)
defp options(:company_contact, [:company_contact, %{id: id}]), do: buid_options(id)
defp options(:contact, [:contact, _]), do: true
defp options(:contact, _), do: false
defp options(_, _), do: []
defp buid_options(id), do: [disabled: true, selected: id]
end
First Post!
bilalhassankh
Anyone?
Popular in Questions
I have a another noob question about loop. Since elixir is immutable, while loop is not directly possible.
total = 10
while total != 0
...
New
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
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
Could someone help me? I’m making my first elixir program, number guessing game. I can’t figure out how to convert the user’s guess from ...
New
Hi all,
I’ve just started learning Elixir and Phoenix Framework, so please pardon my n00bness at this stage.
I’m trying to use Postgres...
New
I am trying to figure out how Mix knows whether the environment is test, dev, or prod – where is this set?
Thanks.
New
Hello, I get Persian date from my client and convert it to normal calendar like this:
def jalali_string_to_miladi_english_number(persi...
New
Hey,
Just curious what are the main benefits of Elixir compared to Clojure?
When is Elixir more useful than Clojure and vice versa?
Th...
New
When I run the Plug and I recompile I wind up having to use Ctrl C to quit iex and start again. Witht the help of rlwrap I can use the cu...
New
Hi!
In PHP: $_SERVER[‘SERVER_ADDR’] - in Elixir?
Searched the docs for ip address and the web, no good results.
Thanks!
New
Other popular topics
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
What is the difference between System.get_env and Application.get_env? For example, what are best practices to use one versus another.
New
As promised, the first release candidate of Phoenix 1.3.0 is out! This release focuses on code generators with improved project structure...
New
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
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
I tried installing
elixir 1.11.2
erlang 23.3.4
via asdf in my zsh shell. Enabled the versions locally and globally.
When I list them ...
New
Credo is smart enough to check for (something like) this:
assert length(the_list) == 0
with this response:
Checking if an enum is empt...
New
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
Got a question about when to concat vs. prepending items to list then reversing to achieve appending.
So i know lists boil down to [1 | ...
New
Seen any cool LiveView demos, sample apps or examples? Please post them here! :003:
New
Categories:
Sub Categories:
Forums
Popular Tags
- #ecto
- #liveview
- #troubleshooting
- #learning-elixir
- #deployment
- #library
- #erlang
- #testing
- #genserver
- #mix
- #absinthe
- #remote-other
- #otp
- #plug
- #how-to-question
- #macros
- #postgres
- #channels
- #elixirconf
- #exunit
- #discussion
- #code-sync
- #javascript
- #podcasts
- #onsite
- #dialyzer
- #docker
- #authentication
- #umbrella
- #full-time-contract
- #podcasts-by-brainlid
- #ecto-query
- #elixir-ls
- #phoenix_html
- #iex
- #blog-post
- #graphql
- #genstage
- #ai
- #websockets
- #supervisor
- #advent-of-code
- #elixirconf-us
- #distillery
- #processes
- #forms
- #api
- #metaprogramming
- #security
- #performance









