@Diesel-nick

Rails 5 — как сделать динамическое добавление пользователей во вложенную форму (по аналогии с Cocoon, но искать пользователей в одном поле поиска)?

Привет.
В приложении есть три модели: team, user и team_user (has_namy: through). В форме для экшена new и edit нужно сделать динамическое добавление пользователей - искать пользователей при помощи AJAX запроса в одном поле user search box и добавлять как нередактируемое значение под форму user search box как показано на примере ниже (выбрать из значений jQuery Autocomplete):

c28ba10c0c264b248f96360522679f6a.gif

Модели:
app/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


app/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


app/models/team_user.rb
class TeamUser < ApplicationRecord
  belongs_to :team
  belongs_to :user
  accepts_nested_attributes_for :team, :user, allow_destroy: true
end


Сложности, которые пока не решил:
  • Если реализовать через Cocoon Gem, то он создаёт новый паршл с новой формой для поиска пользователей. И при этом оставляет возможность редактировать ранее добавленных пользователей в основную форму (на примере выше я показываю, что добавленные пользователи должны быть не редактируемые, и их можно только удалить)
  • Если реализовать через AJAX, то когда я создаю новую команду в экшена new TeamsController @team = Team.new, то эта команда не сохраняется для того чтоб потом в другом экшене (new_team_user AJAX экшн контроллера команд) создать нового пользователя этой команды @team.team_users.build(user_id: params[:user_id]). Т.е. user_id для сохранения в модель team_user я получаю из поля поиска пользователей с jQuery Autocomplete, а саму команду @team не знаю (точнее не запоминаю после создания новой команды)

    class TeamsController < ApplicationController
      before_action :set_team, only: [:show, :edit, :update, :destroy]
      before_action :set_team_ancestry, only: [:new, :edit, :create, :update, :destroy]
      before_action :set_team_users, only: :edit
      # before_action :set_new_team_user, only: [:new, :edit]
      before_action :set_team_users_collection, 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
      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
      
      # GET /teams/1/search_team_user
      def search_team_user
        @users = User.order(:first_name).where("first_name like ?", "%#{params[:term]}%")
        render json: @users.map { |u| { value: u.id, label: u.name } }
      end
      
      # GET /teams/1/new_team_user
      def new_team_user
        @team = Team.find(params[:id])
        @new_team_user = @team.team_users.build(user_id: params[:user_id])
      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 = @team.team_users
        end
        
        # def set_new_team_user
        #   @new_team_user = @team.team_users.build
        # end
        
        def set_team_users_collection
          @team_users_collection = User.all.order(:last_name, :first_name).collect { |p| [ p.name, p.id ] }
        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




Как правильно реализовать задачу как показано на картинке выше выше?
  • Вопрос задан
  • 152 просмотра
Пригласить эксперта
Ваш ответ на вопрос

Войдите, чтобы написать ответ

Войти через центр авторизации
Похожие вопросы