Rails 5 - 如何使用自动完成功能向表单动态添加嵌套对象
Rails 5 - how to dynamically add to the form a nested object using autocomplete
我有 3 个模型 - 团队、用户和 team_user(has_namy:通过)。以编辑和新团队的形式,可以使用自动完成输入动态添加该团队的成员。
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,
@team = Team.new
运行 仅在 TeamsController
中的新操作中,而 Rails 不记得创建 @team
,当 AJAX 试图创建 team_user
对象时。要创建 team_user
模型的对象需要 运行 @team.team_users.build(user_id: params[:user_id])
。 user_id
我从自动完成字段中获得,但不知道 @team
和 team_id
(例如,在 new
操作 TeamsController
中)。
1.
在此示例应用程序中,rail263 example application,我使用 cocoon、simpleform 和 select2 创建一个可搜索的下拉框来搜索姓名列表以将乘客添加到租赁记录。
我相信这就是您想要的用例。
这样做的部分在这里:Partial for passenger lookup
它使用 cocoon 回调来为每位新乘客进行 select2 查找 运行。
在rental record model中,关联是:
belongs_to :customer
belongs_to :vehicle
# delete associated records..
has_many :passengers, dependent: :destroy
has_many :pasenger_lists, :through => :passengers, :class_name => 'PasengerList'
accepts_nested_attributes_for :pasenger_lists
accepts_nested_attributes_for :passengers, allow_destroy: true
激活 select2 下拉菜单的回调在这里:callback
$('#passengers')
.on('cocoon:after-insert', function() {
$(".dgselect2").select2({
});
在您的代码中,您是否将强参数中需要的项目列入白名单?看这里:controller
params.require(:rental_record).permit(
:customer_id, :vehicle_id, :start_date, :end_date, :lastUpdated,
passengers_attributes: [:id, :description, :name, :output, :pasenger_list_id, :_destroy , pasenger_lists_attributes: [:id, :clocknum, :name, :active, :_destroy]]
)
2.
我在这个应用程序中也做了同样的想法:training app
只是rail263 app不同型号而已。这是沿着同样的路线。我使用 rail263 来开发要在培训应用程序中使用的想法。
您可以在此处试用培训应用程序:demo
- 使用用户 = reg 和密码 = a2a2
登录
- 单击 add tr_training_employee
按钮查看它是否正常工作。
3.
如果您对这个想法感兴趣,我可以与您一起编辑此 post 以包含更完整的答案,并向以后可能阅读此主题的其他人解释它的工作原理。让我知道。
相关:cocoon issue
我解决了一个非常相似的问题,使用 cocoon 嵌套属性和 AngularJS 与 jQuery (Angular UI Typeahead)。有一些要点:
使用Angular/jQuery更新data-association-insertion-template
和更新相关data()
每次选择的东西。由于浏览器对数据元素的缓存特性,此属性的更改不会自动反映出来。所以我绑定了按钮的 click
事件:
$(this).data('association-insertion-template', $(this).attr('data-association-insertion-template'));
相应地为 cocoon 编写嵌套字段模板,以便您可以用选定的值填充它。当我使用 Angular 时,我的就像 (Slim 模板语法):
tr.nested-fields
td
= f.object.persisted? ? f.object.full_name : '{{angularModel.full_name}}'
该前端原型几乎可以正常工作,但在每个父对象更新时,所有现有的嵌套字段都会翻倍。所以我覆盖了父模型中的嵌套属性方法(参见 this thread):
def items_attributes=(attributes)
self.items = attributes.values.map { |item| Item.find(item['id']) }
super(attributes)
end
最后一个问题是我可以多次添加嵌套记录。为了限制这种行为,我只是在 typeahead AJAX 查询中删除所有已经使用的 ID。
希望这对您有所帮助。
如果你有类似的项目,你可以用这个解决这个问题gemdynamic_nested_forms
我有 3 个模型 - 团队、用户和 team_user(has_namy:通过)。以编辑和新团队的形式,可以使用自动完成输入动态添加该团队的成员。
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,
@team = Team.new
运行 仅在TeamsController
中的新操作中,而 Rails 不记得创建@team
,当 AJAX 试图创建team_user
对象时。要创建team_user
模型的对象需要 运行@team.team_users.build(user_id: params[:user_id])
。user_id
我从自动完成字段中获得,但不知道@team
和team_id
(例如,在new
操作TeamsController
中)。
1.
在此示例应用程序中,rail263 example application,我使用 cocoon、simpleform 和 select2 创建一个可搜索的下拉框来搜索姓名列表以将乘客添加到租赁记录。
我相信这就是您想要的用例。
这样做的部分在这里:Partial for passenger lookup
它使用 cocoon 回调来为每位新乘客进行 select2 查找 运行。
在rental record model中,关联是:
belongs_to :customer
belongs_to :vehicle
# delete associated records..
has_many :passengers, dependent: :destroy
has_many :pasenger_lists, :through => :passengers, :class_name => 'PasengerList'
accepts_nested_attributes_for :pasenger_lists
accepts_nested_attributes_for :passengers, allow_destroy: true
激活 select2 下拉菜单的回调在这里:callback
$('#passengers')
.on('cocoon:after-insert', function() {
$(".dgselect2").select2({
});
在您的代码中,您是否将强参数中需要的项目列入白名单?看这里:controller
params.require(:rental_record).permit(
:customer_id, :vehicle_id, :start_date, :end_date, :lastUpdated,
passengers_attributes: [:id, :description, :name, :output, :pasenger_list_id, :_destroy , pasenger_lists_attributes: [:id, :clocknum, :name, :active, :_destroy]]
)
2.
我在这个应用程序中也做了同样的想法:training app
只是rail263 app不同型号而已。这是沿着同样的路线。我使用 rail263 来开发要在培训应用程序中使用的想法。
您可以在此处试用培训应用程序:demo
- 使用用户 = reg 和密码 = a2a2
登录
- 单击 add tr_training_employee
按钮查看它是否正常工作。
3.
如果您对这个想法感兴趣,我可以与您一起编辑此 post 以包含更完整的答案,并向以后可能阅读此主题的其他人解释它的工作原理。让我知道。
相关:cocoon issue
我解决了一个非常相似的问题,使用 cocoon 嵌套属性和 AngularJS 与 jQuery (Angular UI Typeahead)。有一些要点:
使用Angular/jQuery更新data-association-insertion-template
和更新相关data()
每次选择的东西。由于浏览器对数据元素的缓存特性,此属性的更改不会自动反映出来。所以我绑定了按钮的 click
事件:
$(this).data('association-insertion-template', $(this).attr('data-association-insertion-template'));
相应地为 cocoon 编写嵌套字段模板,以便您可以用选定的值填充它。当我使用 Angular 时,我的就像 (Slim 模板语法):
tr.nested-fields
td
= f.object.persisted? ? f.object.full_name : '{{angularModel.full_name}}'
该前端原型几乎可以正常工作,但在每个父对象更新时,所有现有的嵌套字段都会翻倍。所以我覆盖了父模型中的嵌套属性方法(参见 this thread):
def items_attributes=(attributes)
self.items = attributes.values.map { |item| Item.find(item['id']) }
super(attributes)
end
最后一个问题是我可以多次添加嵌套记录。为了限制这种行为,我只是在 typeahead AJAX 查询中删除所有已经使用的 ID。
希望这对您有所帮助。
如果你有类似的项目,你可以用这个解决这个问题gemdynamic_nested_forms