tagmanager
tagmanager copied to clipboard
Add Support for Differentiating Between Tag Value/ID and Display Name
I would like to utilize this plugin for a user selection field.
Say I have a users table that maps an ID to non-unique names (e.g. John Doe). As it is, if I wanted to search by the user's name, this plugin would post the name upon form submission. Ideally, it would be great if support were added to retrieve and post the ID for the entries instead of the display values.
So, typeaheadAjaxSource should produce JSON similar to that below:
{"tags":[{"tag":"Pisa", "id":1},{"tag":"Rome", "id":2},{"tag":"Milan", "id":3},{"tag":"Florence", "id":4},{"tag":"New York", "id":5},{"tag":"Paris", "id":6},{"tag":"Berlin", "id":7},{"tag":"London", "id":8},{"tag":"Madrid", "id":9}]}
The value of the tag attribute is displayed, while the value of the id attribute is actually submitted.
To make it really work in all scenarios it would have to support id creation which is making things a little bit more complex. I mean if you only use it to display existing tags you get all tags and their id's with the ajax call, but when the user type a new tag you don't have a id for it.
I would also need the support for id.
Ryan Bates showed a nice solution for that problem. http://railscasts.com/episodes/382-tagging?view=asciicast
He used a server side solution for this, which he parses later.
def self.tokens(query)
authors = where("name like ?", "%#{query}%")
if authors.empty?
[{id: "<<<#{query}>>>", name: "New: \"#{query}\""}]
else
authors
end
end
@max-favilli, it would be great, if you could support this
i would also needed to support it but unfortunately didn't find any solution for this. so i decide to do it for my self,i make some changes in bootstrap-tagmanager.js and bootstrap-typeahed file to support this feature. this is very simple change to support override render in typeahead
this.render = this.options.render || this.render
so i add render in my Js file like this
$("#tagsBox").typeahead({
render: function (items) {
var that = this;
items = $(items).map(function (i, item) {
i = $(that.options.item).attr('data-value', item);
var user = person[item];
i.attr('data-id', user.PersonId);
i.find('a').html(that.highlighter(item));
return i[0];
});
items.first().addClass('active');
this.$menu.html(items);
return this;
},
and in tagmanager i change pushTag
if (!tag || (!isValid) || tag.length <= 0) return;
var valueId = null;
if (tag instanceof Array)
{
valueId = tag[1];
tag = tag[0];
}
and
f (isSelectedFromList) {
// if user selected from list
var user_input = $(this).data('typeahead').$menu.find(listItemSelector).attr('data-value');
var user_value = $(this).data('typeahead').$menu.find(listItemSelector).attr('data-id');
user_input = trimTag(user_input);
if (queuedTag == jQuery(this).val() && queuedTag == user_input) {
isClear = true;
} else {
if (user_value != "") {
var newData = [user_input, user_value];
pushTag(newData, null, true);
} else {
pushTag(user_input, null, true);
}
with this changes i can pass this kind of Json as simple as abc
[{"PersonId":1,"Title":"مهدی فرهانی"},{"PersonId":1002,"Title":"مهدی درعلی"},{"PersonId":1003,"Title":"مهدی لطفی"}]
@tmaier @Mahdi-Farhani @clintonb @max-favilli this looks possible with https://github.com/twitter/typeahead.js/ (which will become the typeahead library of Bootstrap 3). There's also PR #93 which adds support for typeahead.js, I think it actually allows us to bypass a lot of the Ajax functions in TagManager. Please take a look.
Thanks @johnnyshields.
Hmmm so u suggest not to use tagmanager if i want pass also ids?
var read = $("#permissions-read").tagsManager();
$("#permissions-read").typeahead({
valueKey: 'name',
limit: 15,
remote: '/mypath_to_jsondata'
}).on('typeahead:selected', function (e, d) {
read.tagsManager("pushTag", d.name);
owner_read_ids = $("input[name='hidden-owner_read']");
owner_read_ids.val(owner_read_ids.val().replace(d.name, d.id));
});
there is my simple hook to replace name by id after add tag, but that wont work for prefilled data. Any suggestions ? For now instead of giving prefilled data array i just iterate by my data and go with
read.tagsManager('pushTag', el.name);
owner_read_ids = $("input[name='hidden-owner_read']");
owner_read_ids.val(owner_read_ids.val().replace(el.name, el.id));
after initialize tagManager , but that seems really ugly, escpeially if i have few tagManagers on 1 site
it would be just great if i could pass object with value and id to pushTag (also to prefile) instead of string
@panSarin currently TagManager doesn't support IDs.
It would be great if someone could raise a PR which provided dual-support for array (non-id) and hash (tag: value) type tags.