tagmanager icon indicating copy to clipboard operation
tagmanager copied to clipboard

Add Support for Differentiating Between Tag Value/ID and Display Name

Open clintonb opened this issue 12 years ago • 8 comments

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.

clintonb avatar Sep 21 '12 18:09 clintonb

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.

max-favilli avatar Sep 21 '12 20:09 max-favilli

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

tmaier avatar Mar 16 '13 22:03 tmaier

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":"مهدی لطفی"}]

Mahdi-Farhani avatar Apr 08 '13 16:04 Mahdi-Farhani

@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.

johnnyshields avatar May 29 '13 21:05 johnnyshields

Thanks @johnnyshields.

clintonb avatar May 29 '13 21:05 clintonb

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

panSarin avatar Nov 18 '13 19:11 panSarin

it would be just great if i could pass object with value and id to pushTag (also to prefile) instead of string

panSarin avatar Nov 18 '13 19:11 panSarin

@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.

johnnyshields avatar Nov 18 '13 19:11 johnnyshields