jQuery Tag-It - using a value and label object list
Asked Answered
C

7

14

Just tried the excellent Tag-It! plug-in for jquery (http://aehlke.github.com/tag-it/), but I can't get it to work how I would like.

I have an object list like this:

var food = [{value:1,label:'Pizza'},{value:2,label:'Burger'},{value:3,label:'Salad'}];

Which I pass to the tagSource option in my setup:

$("#my_food_tags").tagit({
    tagSource: food,
    singleField: true,
    singleFieldNode: $("#my_food"),
    placeholderText: "Start typing a food name"
});

This works fine, except when I click the auto-complete list item, it displays the numeric value in the tag, rather than the food name.

Therefore, it is possible to have to 'value' entered in to the hidden field, and the 'label' to show as the tag name?

Here is a screen-shot of what I mean. The value is appearing in the tag label, and the label is being lost to the ether ;-)

Example of label text being lost

Could anyone please help me here? It would be very much appreciated!

Thanks in advance, Seb

Cupid answered 3/4, 2012 at 16:24 Comment(2)
Could you post an example? In the code it appends "Label" to the LI so i would think it exactly that. But i guess not? :)Gibber
Certainly Marco - I've added a screen-shot to elaborateCupid
G
5

Tried playing around with it, see: http://jsfiddle.net/pDrzx/46/

What i did:

Extendend the createTag function with the labelname

 createTag: function(labelname, value, additionalClass)

And called it on the label creation var

var label = $(this.options.onTagClicked ? '<a class="tagit-label"></a>' : '<span class="tagit-label"></span>').text(labelname);

Then i made sure that the hidden input field had the number value(for saving purpose)

  if (this.options.singleField) {
        var tags = this.assignedTags();
        tags.push(value);
        this._updateSingleTagsField(tags);
    } else {
        var escapedValue = value;
        tag.append('<input type="hidden" style="display:none;" value="' + escapedValue + '" name="' + this.options.itemName + '[' + this.options.fieldName + '][]" />');
    }

And finally i added the labelname to the autocomplete and focus

        // Autocomplete.
        if (this.options.availableTags || this.options.tagSource) {
            this._tagInput.autocomplete({
                source: this.options.tagSource,
                select: function(event, ui) {
                    // Delete the last tag if we autocomplete something despite the input being empty
                    // This happens because the input's blur event causes the tag to be created when
                    // the user clicks an autocomplete item.
                    // The only artifact of this is that while the user holds down the mouse button
                    // on the selected autocomplete item, a tag is shown with the pre-autocompleted text,
                    // and is changed to the autocompleted text upon mouseup.
                    if (that._tagInput.val() === '') {
                        that.removeTag(that._lastTag(), false);
                    }
                    that.createTag(ui.item.label,ui.item.value);
                    // Preventing the tag input to be updated with the chosen value.
                    return false;
                },
            focus: function(event, ui) {
                event.preventDefault();
                that.createTag(ui.item.label,ui.item.value);
            }
            });

So whats missing, well you need to make sure it passes the labelname in all the createTag methods, but that shouldnt be too hard :)


UPDATED WITH FOCUS (INSPIRED BY @Edwin)

Gibber answered 5/4, 2012 at 22:40 Comment(4)
The close button is on top of the text. Fix : Change .addClass('tagit-choice ui-widget-content ui-state-default ui-corner-all') to .addClass('tagit-choice ui-widget-content ui-state-default ui-corner-all tagit-choice-editable')Saltworks
Thanks Marco :). I noticed one more issue in that. If we use the down arrow key to select the suggestion, then the id of the label will be displayed in the textbox. :)Saltworks
@AbhilashV Did you ever find a solution to your last comment? I am have the exact same problem. Any feedback on how to use the down arrow would be great. If I use it right now, it shows the number.Rightly
as stated this answer does NOT work if you use the keyboard options (down arrow) which to me is a showstopperRegulate
G
4

The most easiest thing is to get plugin that actually support this. That is Select2 or Chosen.

Gunning answered 28/11, 2013 at 13:1 Comment(2)
Thank you for sharing. Select2 is the way to go, i found out.Poinsettia
this is golden advice but just cant go with this because of legacy uses of tag-it pluginEdmund
W
2

The easiest way I've found to solve this problem is to change this line in the tag-it Javascript source:

that.createTag(ui.item.value);

to

that.createTag(ui.item.label);

This is part of the Autocomplete section of code starting on line 216 in my editor:

// Autocomplete.
            if (this.options.availableTags || this.options.tagSource) {
                this._tagInput.autocomplete({
                    source: this.options.tagSource,
                    select: function(event, ui) {
                       // Lots of comments here
                        if (that._tagInput.val() === '') {
                            that.removeTag(that._lastTag(), false);
                        }
                        that.createTag(ui.item.value);
                        value.
                        return false;
                    }
                });
            }
Wapiti answered 13/4, 2012 at 7:50 Comment(1)
but what if you want to show the label but store the Id in the hidden fieldRegulate
C
2

Inside the tag-it.js file where he commented with //Autocomplete, add an event option focus like I did below. This should fix it.

 // Autocomplete.
        if (this.options.availableTags || this.options.tagSource || this.options.autocomplete.source) {
            var autocompleteOptions = {
                select: function(event, ui) {
                    that.createTag(ui.item.value);
                    // Preventing the tag input to be updated with the chosen value.
                    return false;
                },
                focus: function(event, ui) {
                    event.preventDefault();
                    that.tagInput.val(ui.item.label);
                }

            };
Complicated answered 12/12, 2012 at 19:58 Comment(1)
Doesn't work at all. Also the purpose of focus in this case totally is unclear.Squamosal
I
1

Here's another workaround (assuming you want to use data-id attribute):

  var clone = $('#tags').clone();
  // important to clone before calling tagit()
  $('#tags').tagit({
     beforeTagRemoved: function(event, ui) {
        var item_id = clone.find('li:contains('+ui.tagLabel+')').data('id');
        // do something with item_id / tag ui
     }
  });

Accompanying HTML:

<ul id="tags">
 <li data-id="38">Item A</li>
 <li data-id="19">Item B</li>
</ul>
Irritating answered 28/1, 2014 at 19:14 Comment(1)
Why would you assign an id to an item that you just removed?Squamosal
C
0

Overwriting focus event to handle both label and value is not straightforward. My solution consisted of utilizing close to create the tag using a saved reference of the last ui.item from a focus event:

$$("#search-widget-input")
.tagit(
    {
    placeholderText : 'Select or type a location, postcode or Web ID',
    autocomplete : {
        delay : 200, 
        minLength : 1,
        search : function(event, ui) {
            ...
        },
        select: function(event, ui) {
            // use the item's label instead of value
            $$("#search-widget-input").tagit("createTag", ui.item.label, '__value__' + ui.item.value);
            return false; // prevents the tag input to auto tag the ui.item.value 
        },
        focus: function(event,ui) {
          // `focus` event does not fire `select` but does fires `close` event
          // so we store our `ui.item` which allows us to reference it in `close` event
          event.preventDefault();
          self.oAutoCompleteSavedLastUiItem = ui.item;
        },
        close: function(event, ui) {
          event.preventDefault();
          $$("#search-widget-input").tagit("createTag", self.oAutoCompleteSavedLastUiItem.label, '__value__' + self.oAutoCompleteSavedLastUiItem.value);
          return false; // prevents the tag input to auto tag the ui.item.value 
        },
        source : function fAutocompleteSource(oRequest, fResponse) {
            ...
        }
        ...
    }
    ...
});
Cindicindie answered 24/10, 2014 at 17:22 Comment(0)
E
0

Hi I just done it for my project with PHP.

I modified plugins at some point so use script from jsfiddle script section.

Look here i have made full working key value pair script https://jsfiddle.net/656pnLsd/

<ul id="tag_list">
      <li data-value="2">test2</li>
<ul>
<script>
var tag_sources = [{value:1,label:'test1'},{value:2,label:'test2'}];
            console.log(tag_sources);
            jQuery(document).ready(function() {
              var eventTags = $('#tag_list');
                   eventTags.tagit({
                    availableTags: tag_sources,
                    fieldName: "bento4_tags",
                    singleField: true,

                }); 
            });
</script>

UPDATED WITH FOCUS (INSPIRED BY @Edwin and Marco Johannesen)

Eugene answered 27/2, 2016 at 12:54 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.