-1

I'm trying to build a nested form, but I can't get it to work. I'm using rails 5.2, devise and wicked wizard. I have tried to use the cocoon gem, but without luck. The problem is, that the nested form doesn't show up on the page, it's just a blank section on the page.

This is what I have tried so far with the cocoon gem installed, and I have added //= require cocoon to application.js.

I have a user table and a services table. The service table is the nested form.

This is how I created the services table

class Services < ActiveRecord::Migration[5.2]
  def change
    create_table :services do |t|
      t.string :name
      t.text :description
      t.integer :duration
      t.integer :price
      t.timestamps
  end
end
end

I have added a foreign key to the services table like this

AddUserReferenceToServices

class AddUserReferenceToServices < ActiveRecord::Migration[5.2]
  def change
    add_reference :services, :user, foreign_key: true
  end
end

I have created these relations

user.rb

class User < ApplicationRecord
    has_many :services
    accepts_nested_attributes_for :services, reject_if: :all_blank, allow_destroy: true
end

service.rb

class Service < ApplicationRecord
    belongs_to :user
end

I have added values to the user params

def user_params

  params.require(:user).permit(clinic_images: [], profession_ids: [], speciality_ids: [], services_attributes: [:id, :description, :name, :duration, :price, :_destroy])

end

main_form.html.erb

<div class="content">
    <%= simple_form_for @user, url: wizard_path, method: :put do |f| %>
    <div class="specializations-section">
        <h2 class="page-title">Professioner</h2>
        <div class="field select-field ">
            <%= f.association :professions, input_html: { id: 'professions-select', class: 'js-example-basic-multiple' } %>
        </div>
        <div class="content">
            <p>Mangler der en profession på listen? Så skriv til os på&nbsp;<a href="mailto:info@betterwing.dk?Subject=Forslag%20til%20ny%20profession">info@betterwing.dk</a></p>
        </div>
    </div>


    <div id="services">
        <%= f.simple_fields_for :services do |t| %>
        <%= render 'services/services_fields', :f => t %>
        <% end %>
    <div class="links">
      <%= link_to_add_association 'add services', f, :services, :partial => 'services/services_fields' %>
    </div>
</div>

services/_services_fields.html.erb

<%= f.input_field :name, required: true, autofocus: true, autocomplete: "Navn på behandling", placeholder: "Navn på behandling" %>
<%= f.input_field :description, required: true, rows: '1', autofocus: true, autocomplete: "Beskrivelse af behandling", placeholder: "Beskrivelse af behandling"%>
<%= f.input_field :duration, required: true, rows: '1', autofocus: true, autocomplete: "Tid", placeholder: "Tid"%>
<%= f.input_field :price, required: true, rows: '1', autofocus: true, autocomplete: "Pris", placeholder: "Pris"%>

<%= link_to_remove_association 'x', f %>

registration_steps_controller.rb

class RegistrationStepsController < ApplicationController


    include Wicked::Wizard
    steps :company_general, :company_images, :practitioners_general, :practitioners_professions, :practitioners_educations

    def new
      @user.services.new 
    end

    def show
   @user = current_user    
   render_wizard 
    end

    def update
      @user = current_user
      # Change @user.attributes(user_params) by @user.update_attributes(user_params)
      @user.update_attributes(user_params)
      render_wizard @user
    end




private
    def user_params

      params.require(:user).permit(clinic_images: [], profession_ids: [], speciality_ids: [], services_attributes: [:id, :description, :name, :duration, :price, :_destroy])

    end


end
kvnirvana
  • 71
  • 1
  • 8
  • Is this now actually solved? Because the accepted answer will do 1) create an empty service to fill in (actually no need, unless you really want to --one could always will till a user presses the button to add a new service?) and the `simple_fields_for` as suggested is just plain wrong. So not sure how that answers anything? But I also do not see a real error, except maybe for 1) missing a surrounding div for your nested element and 2) not closing your div's. – nathanvda Feb 19 '20 at 09:35
  • Yes it is now solved, it's working with <%= f.simple_fields_for(:services) do |t| %> – kvnirvana Feb 20 '20 at 05:45
  • @nathanvda If you look at the question closely, it says nested_form doesn't show up on page, so it's clear that OP expected a file field to show up in the form when it is loaded and that's why we initialize an empty object in the controller to show atleast one nested form object in the form on page load. Ofcourse you can add more with the help of `add` button. So, it's better to go through the question details properly before drawing conclusions, sir. – Rajdeep Singh Feb 20 '20 at 09:55
  • Maybe @RajdeepSingh should read my comment more precisely. I said the controller change was not needed (but not wrong). But the `simple_fields_for @user.services.new` is wrong because it will never iterate over the set of saved `services`. And OP: adding the parentheses actually does not change anything, so you must have changed something else. But very happy you got it fixed!! – nathanvda Feb 20 '20 at 10:06
  • @nathanvda If you look at my answer again before suggesting `simple_fields_for @user.services.new`, I added a line `or if you have different forms for new and edit, you can try this`, by that I meant you can try this since it is for the `new` action and if the `form` partial is not shared once can definitely try that approach. – Rajdeep Singh Feb 20 '20 at 10:13
  • Ok, that is correct indeed. However confusing :P (I generally only advice the first part of your answer). – nathanvda Feb 20 '20 at 10:30
  • 1
    @nathanvda I just reworded that line to make it less confusing. However I suggested the second approach when the first approach didn't work for the OP. You can see the conversation in answer comments section, nothing seemed to work for the OP, so just tried to help him out. – Rajdeep Singh Feb 20 '20 at 11:15

1 Answers1

0

You need to instantiate the object, in controller action

@user.services.new

or if this partial is only used in new form not shared with edit form, you can try this

<%= f.simple_fields_for @user.services.new do |t| %>

Give it a try!

Rajdeep Singh
  • 17,621
  • 6
  • 53
  • 78