Rails 5 - how to dynamically add nested fields in an edit form?

For a month now, trying to solve the problem at a glance, it’s not very difficult: There are 3 models - team, user and team_user (has_namy: through) In the editing form and a new team to dynamically add members to this team.

Scenario:

  • The user comes in a new team form.
  • Designates a team name
  • After selecting the username (team member) field
  • Click the Add Member button
  • After confirmation of membership is added after the team name field in the text field + delete button opposite
  • Remove its name (member) from the selector (since this is already a member of the team)
  • In selite selects the next user and click "Add Member"
  • Click the Submit button to save the new team and team members.

Difficulties:

  • I tried making through the Cocoon gem, but it is impossible to make another parshaly to select the user to be added to it (SELECT), and added the participants (full name - text).
  • If this is done via <% = from_for ... remote: true%> and a separate controller or a new action in the teams_controller controller, these will be two sub-forms (team forms and team_user forms) with its second submission button. Attachment forms, as I understand it, are not buzzing.
  • Changes in the form (changing the team name and adding / removing team members have an account only after clicking on save to basically send the form command).

enter image description here

application / models / user.rb

class User < ApplicationRecord has_many :team_users has_many :teams, through: :team_users accepts_nested_attributes_for :team_users, :teams, allow_destroy: true end 

application / models / team.rb

 class Team < ApplicationRecord has_many :team_users has_many :users, through: :team_users accepts_nested_attributes_for :team_users, allow_destroy: true, reject_if: proc { |a| a['user_id'].blank? } end 

application / models / team_user.rb

 class TeamUser < ApplicationRecord belongs_to :team belongs_to :user accepts_nested_attributes_for :team, :user, allow_destroy: true end 

application / controllers / teams_controller.rb

 class TeamsController < ApplicationController before_action :set_team, :set_team_users, only: [:show, :edit, :update, :destroy] before_action :set_team_ancestry, only: [:new, :edit, :create, :update, :destroy] before_action :set_new_team_user, only: [:new, :edit] before_action :logged_in_user layout 'sidebar' # GET /teams def index @teams = Team.search(params[:search], :name).sorting(params[:sort], params[:direction]).paginate(page: params[:page]) end # GET /teams/1 def show end # GET /teams/new def new @team = Team.new(parent_id: params[:parent_id]) end # GET /teams/1/edit def edit @team_users = @team.team_users end # POST /teams def create @team = Team.new(team_params) respond_to do |format| if @team.save format.html { redirect_to @team, success: t('.flash.success.message') } else format.html { render :new, danger: t('.flash.danger.message') } end end end # PATCH/PUT /teams/1 def update respond_to do |format| if @team.update(team_params) format.html { redirect_to @team, success: t('.flash.success.message') } else format.html { render :edit, danger: t('.flash.danger.message') } end end end # DELETE /teams/1 def destroy @team.destroy respond_to do |format| format.html { redirect_to teams_url, success: t('.flash.success.message') } end end private # Use callbacks to share common setup or constraints between actions. def set_team @team = Team.find(params[:id]) end def set_team_ancestry @team_collection = Team.where.not(id: params[:id]).all.each { |c| c.ancestry = c.ancestry.to_s + (c.ancestry != nil ? "/" : '') + c.id.to_s }.sort{ |x,y| x.ancestry <=> y.ancestry }.map{ |c| ["-" * (c.depth - 1) + c.name,c.id] } end def set_team_users @team_users_collection = User.all.collect { |p| [ p.name, p.id ] } end def set_new_team_user @team_users_new = @team.team_users.build end # Never trust parameters from the scary internet, only allow the white list through. def team_params params.require(:team).permit( :name, :parent_id, team_users_attributes: [:_destroy, :id, :user_id] ) end end 
+6
source share
1 answer

I followed the decision from the DriftingRuby episode . I was able to implement it in my application, as well as configure some functions. Note. This applies to the new and edit forms, but you can easily do this only for the edit form.

0
source

Source: https://habr.com/ru/post/1012872/


All Articles