I have a User model with an associated UserSettings model. Currently I have a user-editable settings form that works fine. Now I want to add an admin interface wherein administrators can edit both the user’s settings, along with other admin-only values directly on User.
I’m a little confused about how to go about this, though. I see inputs_for, but this seems to use embedded schemas rather than associations. Are there any examples of how to create forms for an association, and how to reference them from elsewhere?
inputs_for isn’t an ecto thing at all, it’s a Phoenix.HTML thing, it just creates a new map at the given key containing the form elements within it, it’s perfectly suited for associations.
Oh, interesting. The phienix.html.form docs specifically call out nested
or embedded associations, and I wasn’t sure if embedded/nested
associations were different from belongs_to and friends.
OK, I think I almost have it, but now I’m trying to implement this
without duplication. I have this basic user settings form. Here, PBF
is the Phoenix bootstrap-forms package that builds fields for forms with
Bootstrap styling, errors, etc.:
Then refer to that partial from either within a form, or within an
embedded input. So either the user can change those fields from their
settings screen, or an admin sees those fields alongside other
admin-only fields on the admin screen for a user. Is that possible? I
either need some sort of container component that I can pass f in
either from the form or the input, or some other mechanism I’m not
thinking of yet.
I recognize these are only 3 fields, but I don’t want to potentially
have logic and fields spread out over multiple files if I can avoid it.
<%= form_for @changeset, @action, fn f -> %>
<%= if @changeset.action do %>
<div class="alert alert-danger">
<p>Oops, something went wrong! Please check the errors below.</p>
</div>
<% end %>
<!-- I want the settings inputs here, but not as a separate form.
inputs_for should work here I imagine. -->
<%= PBF.email_input f, :email, input: [autofocus: true] %> <!-- These
settings are admin-only. -->
And then again here:
<%= form_for @changeset, Routes.settings_path(@conn, :update), [method:
"post"], fn f -> %>
<!-- I took the fields from here. inputs_for wouldn't work here I
imagine since I want those inputs directly in this form at the
top-level. -->
<%= PBF.submit f, "Save" %>
So I’m trying to put the same FormData fields both in a top-level form
where they’re modifying a model directly, and in an embedded form where
they’re modifying an association. If I could just dump the string
content of a file directly inline somehow, that’d be exactly what I want
to achieve, though I’d rather make it a function somehow. Can I
parameterize an .eex file somehow? I’d rather leave those fields in
something like an HTML template so designers can work with them more
easily, though I guess I can move them to a view if there isn’t a way.
I’m not even sure you need inputs_for for that, just call <%= render ... whatever info here to pass in %> and put those elements in that other eex file, you’ll then be able to use it in both places.
as a single file fail to compile? f isn’t defined anywhere in that
file, and defining it in a form_for or an inputs_for isn’t equivalent.
One thing that I may not have made clear: first_name, last_name, and
organization are defined on a UserSettings model separate from User. One
form is meant to edit UserSettings, while the other edits User and its
:settings association which is embedded.
I’m sorry, I seem to be doing a bad job of explaining this. I may just
copy the three lines, though I really wish there were some way to just
wrap the above code in an inputs_for so the variable is defined, and not
save to the association when it is being edited directly. I appreciate
the value of precompiled eex but sometimes I wish I had a safe escape
hatch into string templates.