Issue with cast_assoc for nested has_many assoc

please i would like to understand how to implement cast_assoc form for has many relationship using inputs_for for the nested relationship but currently only working for has_one and not implementing for has_many relatiosnhip, when it comes to has many only the main field showing not the associated field:


This is the html aspect of my code:

  <%= form_for @payment_changeset, "#", [phx_submit: :create_payment, phx_change: :validate_payment_entry, phx_target: @myself, id: "capture_account_info"], fn f -> %>
          <div class="border border-gray-300 rounded-lg p-6 bg-white shadow-md">
            <div class="manual-entry-css">
              <div class="flex md:flex-row flex-col items-center justify-between gap-4">
                <%= inputs_for f, :beneficiaries, fn b_changeset -> %>
                  <div class="py-3">
                    <%= select(
                      b_changeset,
                      :bank_id,
                      Enum.map(@bank_names, &{&1.bank_name, &1.id}),
                      required: true,
                      class: "focus:outline-0 px-4 py-2 rounded-l-md w-full border form-control",
                      phx_update: :ignore
                    ) %>
                    <%= hidden_input(b_changeset, :bank_location, value: "local") %>
                  </div>

                  <div class="py-3">
                    <%= text_input(b_changeset, :account_number,
                      required: true,
                      class: "w-full form-control",
                      placeholder: " Account Number"
                    ) %>
                    <p class="block ">
                      <%= error_tag(b_changeset, :account_number) %>
                    </p>
                  </div>
                <% end %>
                <div class="py-3">
                  <%= text_input(
                    f,
                    :balance,
                    class: "w-full form-control",
                    placeholder: "Amount",
                    required: true
                  ) %>
                </div>
              </div>
            </div>
            <div class="flex items-end justify-end lg:mt-2 mt-4">
              <button phx-target={@myself} type="submit" class="btn-primary rounded-sm">
                Add
              </button>
            </div>
          </div>
        <% end %>
      </div>
    <% end %>

please i need help with fixing this problem

Please am stll facing the issue

Hi @bennydreamtech23 can you provide more information? What is the main schema you are operating with? What is the has_many relationship you want to create? What have you tried so far?

2 Likes

i have done the relationship in the schema aspect but when implemented in the form only the has_one relationship is working.
these is the schema for payments that has many beneficiary:

 schema "payments" do
    field(:tax, :float)
    field(:balance, :float)
    field(:currency, :string)
    field(:status, :string)
    belongs_to(:wallet, Data.Schema.UserWallet)
    belongs_to(:sender, UserDb)
    belongs_to(:payment_receiver, Data.Schema.PaymentReceiver)
    has_many(:beneficiaries, Data.Schema.Beneficiary)
    timestamps()
  end.

currently using this changeset from payment to do validation and form submission

def payment_changeset(payment, attrs) do
    payment
    |> cast(attrs, @payment_fields)
    |> cast_assoc(:beneficiaries,
      with: &Beneficiary.changeset_with_account_number_length_validation/2,
      required: true
    )
    |> validate_required(@payment_fields)
  end

these is the schema for the beneficiaries

 schema "beneficiaries" do
    field(:recipient_country, :string)
    field(:bank_location, :string)
    field(:currency, :string)
    field(:bank_name, :string)
    field(:account_name, :string)
    field(:account_number, :string)
    field(:is_deleted, :boolean, default: false)
    belongs_to(:user, UserDb)
    belongs_to(:bank, Bank, foreign_key: :bank_id)
    belongs_to(:payment, Payment, foreign_key: :payment_id)
    timestamps()
  end

currenlty using this changeset for the beneficiary

  def changeset_with_account_number_length_validation(beneficiary, attrs) do
    changeset(beneficiary, attrs)
    |> validate_account_number_length()
  end.

but when i use all these in the form it return all the balance which is a column in the schema of payments in the ui aspect and other attributes related to beneficiary dont work, for the has many relationship but when it comes to has_ one the whole schema for both is shown

Do your payments already have pre-existing beneficiaries? If so, when you are fetching the payment from the database, are you preloading the beneficiaries?

nope, payment dont have pre existing beneficiaries, they both seperate tables

One thing different moving from has_one to has_many is that inputs_for won’t render any inputs if there’s no items unless you tell it to add ones. You might be running into that case.

so how can solve the issue of creating one item and adding more using input for, or is there a way to use the beneficiaries schema and validate it without using it changeset. like using map.merge

Multiple options. I’d suggest the first one, unless that doesn’t work for some reason in your usecase:

The second one can still be educational nontheless.

1 Like

Thank you, i will check them out and give feedback once i am done

1 Like