icicletech/bootstrap-tokenfield-rails

Does bootstrap-tokenfield-rails support specifying a custom template for the result items?

Closed this issue · 8 comments

Hi! Thanks for the really great gem! I was wondering if it supported specifying a template for the result items in the drop-down. The documentation here seems to indicate that the jQuery UI options can be specified in the autocomplete options. I headed over to jQuery UI here and followed the suggestion of specifying the autocomplete._renderItem as a function that returns the template in HTML.

Here is my call to tokenfield():

<script type="text/javascript" charset="utf-8">
  $('input.tokenize-recipients').tokenfield({
    autocomplete: {
      source: <%= tokenfield_source %>,
      delay: 100,
      _renderItem: function(ul, item) {
        return $('<li>')
                .append('<li class="media"><a class="pull-left" href="#"><img class="media-object" src=' + item.profile_picture + ' alt=""></a><div class="media-body"><h4 class="media-heading">' + item.name + '</h4>' + item.email + '</div></li>')
                .appendTo(ul);
      }
    },
    showAutoCompleteOnFocus: true
  });
</script>

where token_source is a helper method defined as such:

  def tokenfield_source
    source = []
    current_user.followed_users.each do |u|
      source << { value: u.email, label: u.name, profile_picture: u.avatar.url }
    end
    raw(source.to_json)
  end

I have tokenfied_source returning what I want correctly, and the label is correctly displaying instead of the value in each component of the Array. So I'm kind of at a loss and looking for a learning opportunity on this one.

Hi @jakehockey10

So, if I got it correct you want to build a dynamic searchable list which has the email, name and avatar url.

According to the example mentioned in the site you should be building the template in this format in _renderItem:

<li class="ui-menu-item" role="presentation">
  <a id="ui-id-2" class="ui-corner-all" tabindex="-1">{your_content}</a>
</li>

Hope this helps, do let me know if the query is something else.

Regards
-Akash

Akash, thanks for your response. Do you know what's wrong with the way I set _renderItem? Based on what you said, I feel like I am doing it right. Also, which example are you referring to on the site? I don't see _renderItem used on that page...

Sorry if I'm misunderstanding. Looking forward to your reply :-)

Im referring to the first example Using jQuery UI Autocomplete. I'm assuming the _renderItem of jquery UI would build the list items and looking at the source of the list items created by the bootstrap-tokenfield plugin i'm inferring you need to build each li in the following manner

<li class="ui-menu-item" role="presentation">
  <a id="ui-id-2" class="ui-corner-all" tabindex="-1">{your_content}</a>
</li>

Hope this helps.

Thanks again for your response. And now I believe that we are both on the same page. In my original comment on this issue, I showed the javascript call to tokenfield() that I'm using. I'm not sure what is wrong with how I have specified the function for the _renderItem. Do you have an idea of what the issue is?

I believe you need to call the _renderItem on the ui-autocomplete div which is created by jquery-ui
as explained here and here

Let me know if that works, also what is the error you are getting in console if any?

Okay, thank you so much for your patience. As soon as I get home, I'll give this a shot and see what I was doing wrong. As of right now, no console errors are appearing, so I was assuming that any syntactical errors are handled silently when specifying jQuery UI Autocomplete options. I'll keep you posted. And again, thank you :)

Hello! I finally got something working! Here is the code that I ended up with:

<script type="text/javascript" charset="utf-8">
  $('input.tokenize-recipients').tokenfield({
    autocomplete: {
      source: <%= tokenfield_source %>,
      delay: 100,
      create: function () {
        $(this).data('ui-autocomplete')._renderItem = function (ul, item) {
          return $('<li>')
                  .addClass('media')
                  .append('<a class="media-left" href="#">' + item.profile_picture + '</a><div class="media-body"><h4 class="media-heading">' + item.label + '</h4>' + item.value + '</div>')
                  .appendTo(ul);
        };
      }
    },
    showAutoCompleteOnFocus: true
  });
</script>
  def tokenfield_source
    source = []
    current_user.followed_users.each do |u|
      source << { value: u.email, label: u.name, profile_picture: raw(avatar_for u, {size: :small, class: 'media-object'}) }
    end
    raw(source.to_json)
  end

It seems like there are a bunch of changes made in different versions of jQuery UI and I just had to find the right example that was written using the same version of jQuery UI that I am using.

@jakehockey10 Good to know you got it working 👍 , yes according to docs you need to call _renderItem on the ('ui-autocomplete').

Thanks for posting back with the solution will be useful for someone else.