Jquery 如何向Rails中的现有模型添加带有autocomplete的标记?
我试图在Rails 3应用程序中向Jquery 如何向Rails中的现有模型添加带有autocomplete的标记?,jquery,ruby-on-rails,autocomplete,tagging,acts-as-taggable,Jquery,Ruby On Rails,Autocomplete,Tagging,Acts As Taggable,我试图在Rails 3应用程序中向文章模型添加“标记” 我想知道是否有一个gem或插件既添加了模型中的“标记”功能,也添加了视图的自动完成帮助器 我发现可以作为标记使用,但我不确定这是否是我应该使用的。有更新的吗?我从2007年的谷歌搜索结果中发现,创业板可能是你最好的选择。我发现许多标签宝石更像是一个“良好的起点”,但随后需要大量的定制才能得到您想要的结果。并很好地协同工作,形成一个如此相似的标签系统,请参见下面的示例。我认为还没有一个适合rails的全能选项 按照以下步骤安装此所有组件: 一
文章
模型添加“标记”
我想知道是否有一个gem或插件既添加了模型中的“标记”功能,也添加了视图的自动完成帮助器
我发现可以作为标记使用
,但我不确定这是否是我应该使用的。有更新的吗?我从2007年的谷歌搜索结果中发现,创业板可能是你最好的选择。我发现许多标签宝石更像是一个“良好的起点”,但随后需要大量的定制才能得到您想要的结果。并很好地协同工作,形成一个如此相似的标签系统,请参见下面的示例。我认为还没有一个适合rails的全能选项
按照以下步骤安装此所有组件:
一,。备份你的rails应用程序2.安装 注意:您可以使用
jqueryrails
安装jqueryui,但我选择不安装
三,。下载并安装
选择一个主题,这将赞美你的网页设计(一定要测试自动完成演示与你选择的主题,默认的主题不适合我)。下载自定义zip并将[zipfile]/js/jquery ui-#.#.#.#.custom.min.js
文件放入应用程序的/public/javascripts/
文件夹中。将[zipfile]/css/custom-theme/
文件夹和所有文件放入应用程序的public/stylesheets/custom-theme/
文件夹
四,。将以下内容添加到您的文件中,然后运行“bundle install”
gem'在'gem'rails3jqueryautocomplete' 五,。从控制台运行以下命令: rails生成作为标记的行为:迁移
rake数据库:迁移
rails生成自动完成:安装
在应用程序中进行这些更改 在应用程序布局中包括必要的javascript和css文件:
<%= stylesheet_link_tag "application", "custom-theme/jquery-ui-1.8.9.custom" %>
<%= javascript_include_tag :defaults, "jquery-ui-#.#.#.custom.min", "autocomplete-rails" %>
查看示例
class Article < ActiveRecord::Base
acts_as_taggable_on :tags
end
<%= form_for(@article) do |f| %>
<%= f.autocomplete_field :tag_list, autocomplete_tag_name_articles_path, :"data-delimiter" => ', ' %>
# note tag_list above is a virtual column created by acts_as_taggable_on
<% end %>
', ' %>
#注:上面的标记列表是由acts作为标记创建的虚拟列
注意:此示例假设您在整个应用程序中仅标记一个模型,并且仅使用默认标记类型:标记。基本上,上面的代码将搜索所有标记,而不是将它们限制为“Article”标记 我最近写了一篇关于这个的文章;为简洁起见,我的方法允许您使用(可选)上下文过滤标记(例如,根据模型和模型上的属性),而@Tim Santeford的解决方案将为您获取模型的所有标记(不按字段过滤)。下面是逐字记录的帖子
我试过了,但问题在于标记结果。在他的解决方案中,您可以通过autocomplete返回所有现有标记,而不局限于您的模型和可标记字段!因此,我提出了一个解决方案,在我看来,这个方案要好得多;它可以自动扩展到您想要标记的任何模型,它非常高效,最重要的是它非常简单。它使用gem和JavaScript库 在gem上安装Acts As Taggable
gem'作为标记添加到',“~>3.5'
bundle install
安装它rake充当引擎上的标记:安装:迁移
rake db:migrate
电影
模型(因为我有)。只需将以下两行添加到模型中:
class Film < ActiveRecord::Base
acts_as_taggable
acts_as_taggable_on :genres
end
请注意,参数不是我们在模型中指定的genres
。不要问我为什么,但在列表中充当标记,这是视图中需要的
到视图层上!我使用gem和模板引擎进行查看,因此如果不使用gem,我的表单可能会与您的表单略有不同。但是,它只是一个正常的文本输入字段:
= f.input :genre_list, input_html: {value: @film.genre_list.to_s}
您需要设置该值的input\u html
属性,以便将其呈现为逗号分隔的字符串(这是控制器中可标记的内容)。当您提交表单时,标签现在应该可以工作了!如果它不起作用,我建议看(神奇的)
将select2集成到表单中
首先,我们需要包括select2库;您可以手动将其包括在内,也可以使用(我的首选项)为Rails资产管道打包select2的gem
将gem添加到您的gem文件中:gem'select2rails'、“~>4.0”
,然后运行bundle安装
在资产管道中包括JavaScript和CSS:
在application.js中:/=require选择2 full
。在application.css中:*=需要选择2
现在,您需要稍微修改表单,以包含select2希望标记的内容。这看起来有点混乱,但我会解释一切。更改以前的表单输入:
= f.input :genre_list, input_html: {value: @film.genre_list.to_s}
致:
我们添加一个隐藏的输入,它将作为发送给控制器的真实值。Select2返回一个数组,其中充当标记,需要一个逗号分隔的字符串。select2表单输入的值更改时将转换为该字符串,并设置为隐藏字段。我们很快就会谈到的
f.input
的id
和name
属性实际上并不重要。它们不能与您的隐藏的输入重叠。数据
散列在这里非常重要。taggable
字段允许我们使用JavaScript一次性初始化所有select2输入,而不是手动按id初始化每个输入。taggable_type
字段用于过滤特定型号的标记,context
字段用于过滤该字段中以前使用过的标记。最后是class FilmsController < ApplicationController
def index
...
end
...
private
def films_params
params[:film].permit(..., :genre_list)
end
end
= f.input :genre_list, input_html: {value: @film.genre_list.to_s}
= f.input :genre_list, input_html: {value: @film.genre_list.to_s}
= f.hidden_field :genre_list, value: @film.genre_list.to_s
= f.input :genre_list,
input_html: { id: "genre_list_select2",
name: "genre_list_select2",
multiple: true,
data: { taggable: true, taggable_type: "Film", context: "genres" } },
collection: @film.genre_list
// Initialize all acts-as-taggable-on + select2 tag inputs
$("*[data-taggable='true']").each(function() {
console.log("Taggable: " + $(this).attr('id') + "; initializing select2");
$(this).select2({
tags: true,
theme: "bootstrap",
width: "100%",
tokenSeparators: [','],
minimumInputLength: 2,
ajax: {
url: "/tags",
dataType: 'json',
delay: 100,
data: function (params) {
console.log("Using AJAX to get tags...");
console.log("Tag name: " + params.term);
console.log("Existing tags: " + $(this).val());
console.log("Taggable type: " + $(this).data("taggable-type"));
console.log("Tag context: " + $(this).data("context"));
return {
name: params.term,
tags_chosen: $(this).val(),
taggable_type: $(this).data("taggable-type"),
context: $(this).data("context"),
page: params.page
}
},
processResults: function (data, params) {
console.log("Got tags from AJAX: " + JSON.stringify(data, null, '\t'));
params.page = params.page || 1;
return {
results: $.map(data, function (item) {
return {
text: item.name,
// id has to be the tag name, because acts_as_taggable expects it!
id: item.name
}
})
};
},
cache: true
}
});
});
class TagsController < ApplicationController
def index
@tags = ActsAsTaggableOn::Tag
.where("name ILIKE ?", "%#{params[:name]}%")
.where.not(name: params[:tags_chosen])
.includes(:taggings)
.where(taggings: {taggable_type: params[:taggable_type]})
@tags = @tags.where(taggings: {context: params[:context] }) if params[:context]
@tags.order!(name: :asc)
render json: @tags
end
end
[
{
"id": 12,
"name": "comedy",
"taggings_count": 1
},
{
"id": 11,
"name": "conspiracy",
"taggings_count": 1
}
]
/*
* When any taggable input changes, get the value from the select2 input and
* convert it to a comma-separated string. Assign this value to the nearest hidden
* input, which is the input for the acts-on-taggable field. Select2 submits an array,
* but acts-as-taggable-on expects a CSV string; it is why this conversion exists.
*/
$(document).on('select2:select select2:unselect', "*[data-taggable='true']", function() {
var taggable_id = $(this).attr('id')
// genre_list_select2 --> genre_list
var hidden_id = taggable_id.replace("_select2", "");
// film_*genre_list* ($= jQuery selectors ends with)
var hidden = $("[id$=" + hidden_id + "]")
// Select2 either has elements selected or it doesn't, in which case use []
var joined = ($(this).val() || []).join(",");
hidden.val(joined);
});