Hello!
I’m newer to Phoenix and fullstack development in general.
I’m wanting to create a controller action that take in two pieces of information in the view.
The business purpose is to create a type of contract between two other tables, a Wholesaler and Retailer which is stored in a Contract table. This is to allow requests to be created between organizations.
Contract
status: string
wholesaler_id
retailer_id
user_id
in my router
resources "/contracts", ContractController
I’m wanting to use the contract create action to create a request with a link. The link occurs within an iterator. I have a current user item assigned to @current_user.
<%= for retailer <- @retailer do %>
<%= link "Request Contract", to: contract_path(@conn, :create, @current_user, retailer.id) %>
<% end %>
When I click the link, I’d want a new contract instance to be created with
The retailer id populating the retail field and the current user id to be user_id. I have a field in the user that would populate the wholesaler id.
I’ve tried a few things in the controller, but I lack a basic understanding of how this works. This is the current iteration. Also let me know if I’m doing this completely wrong and there’s a much smarter way of doing this.
def create(conn, %{"id" => id}, %{"org" => org}) do
retailer_id = id
wholesaler_id = org
map = {"retailer_id" => id, "wholesaler_id" => org}
App.create_contract(map)
end
You can pass like that
<%= link "Request Contract", to: contract_path(@conn, :create, @current_user, param: "test") %>
edit: It is a post request so that doesnt work
2 Likes
What have you done with Phoenix so far?
For example, it would be helpful if you are already familiar with Building Forms, Programming Phoenix ≥ 1.4 p.60. Fundamentally with HTML the create
action is a result of a form being submitted.
resources "/contracts", ContractController
creates among others a POST /contracts HelloWeb.ContractController :create
route which typically the form inside the page loaded with /contracts/new
submits to. When that submit happens, the information inside the form is sent to the server as form data. The form data is essentially a list of key/value pairs - Phoenix turns those key/value pairs into a single Elixir Map. That map is supplied as the second (params
) parameter to the create
action inside the ContractController
.
Given the above the simplest approach is to represent the retailers as radio buttons (the value being the retailer_id
) inside a form. That way the retailer_id
should appear in create
’s params
map value. The current user should be available in the (first) conn
argument (conn.assigns.current_user
) giving you the necessary information.
Don’t forget to redirect at the end to let the user know whether the “contract create” failed or succeeded.
2 Likes
So I have a familiarity of that, but what I’m trying to do is basically list out all the retailers. Then as a wholesaler user I can see a list of the wholesalers with buttons in each row that say “Request Contract.”
When I click that button, I create a new contract in the database. That table will have the retailer’s id (from the iterator), the current user’d id and then the wholesaler’s id (from a field in the user’s info).
I tried that and I got a different error stating the view was unavailable.
If I get You right, You already have the current user id, and this current user is associated with a wholesaler id.
So no need to do anything because these informations come from authentication.
Then You need to create a new contract…
You can get all the requested information with a nested route like this…
/retailers/:id/contracts/new
You will get retailer id from the route.
It’s an HTML problem. I assume that a contract can only be requested once - so processing a contract request should probably remove the button or make the row go away entirely which will require a page reload (the purpose of the redirect).
This is very close and something I would do coming from a Rails understanding. However it doesn’t seem to take. It has something to do with the link. I have a clue: when I define the link as you have here, but put the parameters in a list format, then it will render. I might tool around with that.
‘’’
<%= link “Request Contract”, to: contract_path(@conn, :create, [@create_user, courier.id]) %>
‘’’
You can use a form like that for request. Post request parameters doesnt show in url for security.
#form in view
<%= form_for @conn, contract_path(@conn, :create), [ method: :post] , fn f ->%>
<%= hidden_input f, :retailer_id, value: retailer.id %>
<%= submit "Request Contract", class: "btn btn-primary" %>
<% end%>
#controller function
def create(conn, %{"retailer_id" => retailer_id}) do
map = %{....}
App.create_contract(map)
reditect(conn, to: "/contracts")
end
8 Likes
This solved it! I didn’t even know you could do this! Thank you very, very much! I just need to get the user’s field for wholesaler to pass into the hidden input.