Rails 5 - 如何在编辑表单中动态添加嵌套字段?

Nik*_*sev 7 ajax jquery nested ruby-on-rails has-many-through

已经有一个月试图一眼就解决问题并不是很复杂:有3个模型 - 团队,用户和team_user(has_namy:through)以编辑和新团队的形式,能够动态添加该团队的成员.

场景:

  • 用户加入团队新表单
  • 表示团队的名称
  • 在名称字段之后选择用户(团队成员)
  • 单击"添加成员"按钮
  • 验证成员后,在文本字段+删除按钮对面的团队名称字段后添加
  • 从选择器中删除他的(成员)名称(因为它已经是团队成员)
  • 在selite中选择下一个用户,然后单击"添加成员"按钮
  • 按"提交"按钮以保存新团队和团队成员

难点:

  • 我试图通过gem Cocoon,但是不可能做出不同的parshaly来选择要添加到它的用户(SELECT)并添加了成员​​(全名 - 文本)
  • 如果通过<%= from_for ... remote:true%>以及控制器teams_controller中的单独控制器或新操作完成,它将是两种形式的嵌套(形状和表单团队team_user)及其第二个提交按钮.据我所知,附件表格不是gud.
  • 表单中的更改(更改团队名称和添加/删除团队成员只有在单击保存后基本上提交表单团队才有计数)

在此输入图像描述

应用程序/模型/ 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
Run Code Online (Sandbox Code Playgroud)

应用程序/模型/ 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
Run Code Online (Sandbox Code Playgroud)

应用程序/模型/ team_user.rb

class TeamUser < ApplicationRecord
  belongs_to :team
  belongs_to :user
  accepts_nested_attributes_for :team, :user, allow_destroy: true
end
Run Code Online (Sandbox Code Playgroud)

应用程序/控制器/ 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
Run Code Online (Sandbox Code Playgroud)

dsp*_*cer 2

我遵循DriftingRuby 剧集中的解决方案。我能够在我的应用程序中实现它并自定义一些功能。注意:这适用于newedit表单,但您可以轻松地仅针对表单进行设置edit