joaquinalcerro
Drab partials template
Hi guys,
Following up on this github issue where @grych has been kindly helping:
I have been trying to get this right but still unable to make it work.
I have the basic controller, commander setup but with nested partials as follows:
Controller renders → new.html.drab template
new.html.drab template renders → form.html.drab template
the form.html.drab template renders → _invoices.html.drab template
invoices.html.drab template renders → _invoice_details.html.drab template
I am setting a drab-change event handler in a input checkbox in the last partial invoice_details.
This event handler triggers a update to a assign (po_grantotal) and this assign is located in the form.html.drab template
This are the form.html.drab template assigns:
iex(6)> socket |> assigns("form.html")
[:action, :changeset, :conn, :currency_us, :invoices, :parent, :po_grantotal]
This is a peek at that assign:
iex(7)> socket |> peek("form.html", :po_grantotal)
{:ok, 0}
So my poke call is as follows:
poke socket, "form.html", po_grantotal: 1000
With this setup I get the following error:
** (Protocol.UndefinedError) protocol Enumerable not implemented for nil. This protocol is implemented for: DBConnection.PrepareStream, DBConnection.Stream, Date.Range,
Ecto.Adapters.SQL.Stream, File.Stream, Floki.HTMLTree, Function, GenEvent.Stream, HashDict, HashSet, IO.Stream, List, Map, MapSet, Postgrex.Stream, Range, Scrivener.Page
, Stream, Timex.Interval
(elixir) lib/enum.ex:1: Enumerable.impl_for!/1
(elixir) lib/enum.ex:141: Enumerable.reduce/3
(elixir) lib/enum.ex:1919: Enum.map/2
(epr) lib/epr_web/templates/payment_order/form.html.drab:76: anonymous fn/2 in EprWeb.PaymentOrderView."form.html"/1
(phoenix_html) lib/phoenix_html/form.ex:288: Phoenix.HTML.Form.form_for/4
(epr) lib/epr_web/templates/payment_order/form.html.drab:1: EprWeb.PaymentOrderView."form.html"/1
(phoenix) lib/phoenix/view.ex:332: Phoenix.View.render_to_iodata/3
(phoenix) lib/phoenix/view.ex:339: Phoenix.View.render_to_string/3
(drab) lib/drab/live.ex:683: Drab.Live.rerender_template/4
(drab) lib/drab/live.ex:638: Drab.Live.process_poke/9
Is this a correct setup? What am I doing wrong?
Thanks in advance for your help.
Best regards,
Most Liked
joaquinalcerro
This is the result:
form.html.drab
<%= form_for @changeset, @action, fn f -> %>
<%= inspect(@changeset) %>
<p>---------------------</p>
<%= inspect(@action) %>
<div class="row">
<div class="col-md-12">
<%= render "_invoices.html", conn: @conn, invoices: @invoices, parent: @parent %>
</div>
</div>
............
result printed out in the browser page
#Ecto.Changeset<action: nil, changes: %{}, errors: [date: {"can't be blank", [validation: :required]}, concept: {"can't be blank", [validation: :required]}, check_number: {"can't be blank", [validation: :required]}, bank_account_id: {"can't be blank", [validation: :required]}], data: #Epr.Payments.PaymentOrder<>, valid?: false>
---------------------
"/contracts/2/payment_orders"
This is the Google Chrome Console output for _drab
1. assigns:
1. ge4tcmbtge2dkmzz:
1. invoices: {document: "QTEyOEdDTQ.rkO2qTvBKpBncBjBOUNNhhYj7hrcS__s-bMZkYU…GoDtSb4T2CJn5yhopxEb6dPUAV.1JZQG4HEUiGSDOPx0Vmdug"}
2. parent: {document: "QTEyOEdDTQ.Ar-AaS6DIYytU2srD6pveNYKX862GekZZYZ0PAl…g8kxTBr81V7k25jWLuZzcHPZHQ.bftVt5kyWJS067Z4ncibRA"}
3. __proto__: Object
2. giytanzzha4tgnjs:
1. conn: {document: "QTEyOEdDTQ.GFC8HqSwajb9jUthihlg2dc5L5gJj7axH4U1O0H…00URxfOPRo2I9jyO5HmrEEKm8Q.KZim6LitfLrAs4VTTWBtLA"}
2. parent: {document: "QTEyOEdDTQ.p-wIFXp5VELvZx5v1ub82Zrs3yOt24EWpbsy43s…8h1GOrusAo55428capZCxrT3xs.Yvk7mc9jwyNE0DfhHue51A"}
3. type: {document: "QTEyOEdDTQ.ckW9WiB7ZPC-4dQtE52IBTBAyHmXC6Gxb40MFNL…5FjoWh.AoPxonuHyD4HuDwBsSc.Ni0NIn9tyrkNjlDlzKJ2qg"}
4. __proto__: Object
3. giytkojrgu2tcmbw:
1. currency: {document: "QTEyOEdDTQ.hQz0cCd0ngRDTKs6mqO8qqBnyDJgOvrM792Xs3y…v3SlJSxT1p6aC.m9923cGIFixp.wQ55dmFJyFIhIiQI7LgGhQ"}
2. invoice: {document: "QTEyOEdDTQ.NCrMDyUyPxAuW_b0gEcF1BxWubdSCXEIdMVmhxt…DZZriJfjT2QdNJbjMpZh3dpguj.IBxdtmoBRUt844rZx-2ttA"}
3. __proto__: Object
4. gqzdqojugi4tknbv:
1. action: {document: "QTEyOEdDTQ.EYSw4Vj-VlIEDvRB6FO3lWAyzk_bmw_97LPI18i…Kjjap6YXne1M4gXbBZ92AbJqBh.ffIV6VcHyLsgCXHQsUZyVw"}
2. changeset: {document: "QTEyOEdDTQ.Ff44_w87BhuG5viQ2m75GF9vFpkx4Nge4xFUfxw…6F4LgcLXehjmUh7u9yjk1oo6QK.Pak2S9KU8oJBipZk5mDaJg"}
3. conn: {document: "QTEyOEdDTQ.i7LNqEzjsvqFXlyKZLmWE0Jj-6JHSiJPuQYHCdw…kHWWuSVMYIh7Yr79iuVfwPwayA.8c6o3Ke86NdW1ldEgWoKEw"}
4. currency_us: {document: "QTEyOEdDTQ.Np39iu7OtdlSepYuQsNqHNgCEXaWukWJZ59_4Mu…3U50h-KYB2yqq.c9H97HU6nQYf.5WWwumklVLAT6GO6sPrJQA"}
5. invoices: {document: "QTEyOEdDTQ.1MJXW0GvMPZ4w30_-9zAw15UMJTYyqJwi3s7c33…YHQbELwTuFssGlWn0gBrvcK_io.IGOBBM2E2PTNeDfWbAzKTQ"}
6. parent: {document: "QTEyOEdDTQ.J5hkxodrx40FchLomo7Gmdtvbhzt5nIokzYhTT0…7UZuYxQERun0fAuX7pfaqn6EFw.d0FlWlDgsNLVJgTIXZs2fg"}
7. po_grantotal: {document: "QTEyOEdDTQ.7pdcRGyALNNERy61CMSA6KUTnlagQOxbSymK-a0…0xlk.ZtVS4b1qlgTPZakD.V2Gt.msowySouBcC2oeeqL8ZbFg"}
8. __proto__: Object
Thanks again for the help.
grych
I have no idea what can be wrong then. All looks good, the data given to form_for looks exactly the same, I have no idea where the nil may come from 
joaquinalcerro
So I finally identified the problem. Turns out that I use a Enum function inside the form.html.drab. This is the code:
<%= form_for @changeset, @action, fn f -> %>
<div class="row">
<div class="col-md-12">
<%= render "_invoices.html", conn: @conn, invoices: @invoices, parent: @parent %>
</div>
</div>
.......
.......
<div class="form-group">
<%= label f, "Cuenta de banco", class: "control-label" %>
<%= select f,
:bank_account_id,
Enum.map(assigns[:bank_accounts], &{&1.num, &1.id} ),
class: "form-control",
prompt: "Seleccione un número de cuenta"
%>
<%= error_tag f, :bank_account %>
</div>
Please note that is use assigns[:bank_accounts] instead of @bank_accounts.
The first time this form.html.drab is rendered, this assign is there because I added it in the controller and the form renders correctly with the bank_accounts information:
def new(conn, _params, %Epr.Debts.Contract{} = document) do
invoices = Epr.Debts.list_unpaid_invoices(document)
changeset =
%PaymentOrder{}
|> Payments.new_payment_order()
render(
conn,
"new.html",
changeset: changeset,
parent: document,
invoices: invoices,
bank_accounts: Epr.Payments.list_all_bank_accounts(),
currency_us: document.currency_us,
po_grantotal: 0,
type: "contract"
)
end
But when I check the drab assigns, it is not there:
iex(25)> socket |> assigns("form.html")
[:action, :changeset, :conn, :currency_us, :invoices, :parent, :po_grantotal]
iex(26)>
And when you poke the assign and re-render the form, the assign[:bank_accounts] is nil.
So simple solution was to change the assign[:bank_accounts] to @bank_accounts as I should and now it all works fine.
iex(29)> socket |> assigns("form.html")
[:po_grantotal, :conn, :invoices, :parent, :currency_us, :action,
:bank_accounts, :changeset]
Thanks for your help.
Best regards,







