March 04, 2015

Home » » » Bootstrap Typeahead on Rails App - Typeahead and Gon

Bootstrap Typeahead on Rails App - Typeahead and Gon

Posted by Unknown
0

Try example at : Demo Typeahead

Add Gemfile

gem 'bootstrap-typeahead-rails', '~> 0.10.5.1'
Run command to install gem
$ bundle install

Add gon Gem

gem 'gon'
$ bundle install

Add following line to application.html.erb

<!DOCTYPE html>
<html>
  <head>
    <title>TenderMessenger</title>
    <%= include_gon %>
      ...other scripts, etc.
  </head>

Add Gon to your controllers. The idea is to assign your Rails variable to a Gon variable (which will become a JavaScript variable). In my case, trying to pass users’ names and images, it looked like this:

def index
  gon.usernames = User.pluck(:name)
  gon.gravatars = User.all.map { |user| user.gravatar }
  # ...other code that belongs in the controller action
end

You can assign any array to the Gon variable. Both of my examples return arrays by calling methods (ActiveRecord query for usernames and mapping image links), but you could just as easily do gon.variable = [example1, example2, example3] (though, as we’ll see, you could add this data straight into your JavaScript file)

Assign that Gon variable to a JavaScript variable. In whatever .js file you choose, assign

// Other javascript...
var gravatars = gon.gravatars
var usernames = gon.usernames;
// More javascript

Open application.js

//= require twitter/typeahead
Determine the css selector for the input on which you want to implement typeahead. In my case, I added a class of “typeahead” to my targeted text field as follows:
<!-- ...preceding html/erb... -->
<%= text_field_tag :name_or_email, nil, placeholder: "To: name or email", class: "typeahead" %> 
<!-- ... -->
 
  • In whichever JavaScript file you’ve made the dataset available, add $('.typeahead').typeahead(). Replace “.typeahead” with whatever CSS selector you’re using (see previous step). You now have the entire structure into which you can try the various typeahead.js examples.
     
  • I started with the basics, copying line 1-23 above my typeahead method, and everything withing the curly braces from line 37-44 into my typeahead method. Make sure to change the example’s default variable (“states” in the basic example, “best-pictures” in the custom templates example) to whatever variable you assigned using Gon. Depending on how your Rails app is structured–particularly what your asset pipeline looks like–this may be all you need.
  • I had conflicting stylesheets and JavaScript files, plus I wanted more flexibility creating templates for the typeahead, so I implemented the custom templates example. Full code for what I describe is below.
To begin, I added the templates (lines 28-40). The “empty” template worked easily–the code copied from Twitter’s example worked on its own. I had more difficulty with the “suggestion” template, primarily because I didn’t immediately realize that it’s a function, as opposed to the string that the “empty” template was. At this point, I was able to style the template as I liked, even including an image. pattern of passing entire objects and calling two or more different attributes (best pictures’ names and years in the custom template example), but I was unable to configure my JavaScript this way. Instead, knowing that my “gravatars” array directly mirrored my “usernames”, I used JavaScript’s indexOf() method, as seen in line 37. This enabled me to the the index of a given username and find the gravatar url at that index of the gravatars array. Not ideal, but it worked.
// Twitter Typeahead
$(document).ready(function() {
  var substringMatcher = function(strs) {
    return function findMatches(q, cb) {
      var matches, substringRegex;
      matches = [];
      substrRegex = new RegExp(q, 'i');
      $.each(strs, function(i, str) {
        if (substrRegex.test(str)) {
          matches.push({ value: str });
        }
      });
      cb(matches);
    };
  };
  var gravatars = gon.gravatars;
  var usernames = gon.usernames;
  $('.typeahead').typeahead({
    hint: true,
    highlight: true,
    minLength: 1,
  },

  {
    name: 'usernames',
    displayKey: 'value',
    source: substringMatcher(usernames),
    templates: {
      empty: [
        '<div class="empty-message">',
        'No username matches found. Enter an email instead!',
        '</div>'
      ].join('\n'),
      suggestion: function(username){
        return  '<div id="user-selection">' +
                '<p><strong>' + username.value + '</strong></p>' +
                '<img src="' + gravatars[usernames.indexOf(username.value)] + '"/>' +
                '</div>' ;
      }
    }
  });
});


  • My final issue came with the highlighting. The highlight:true line within the typeahead method indicates that it should work right out of the box, but it did not for me (again, due to conflicting other assets). For this reason, I needed to debug in my JavaScript console, eventually finding that an item selected using typeahead was situated in a div with class of “tt-cursor”. A lot of the default styling was fine with me but, since the highlighting itself did not work, I added the following to my css, thus giving the selected item a background color. “` css styling.css div .tt-cursor { background-color: #16A085; } “` (that selector, “.tt-cursor”, was very important!)
  • And that concludes my adventures with typeahead. It took some time, but, as I described before, it’s those seemingly minor finishing touches that can end up taking the most time. This exercise was certainly proof of that. But it was worth it to get a working—and good-looking—typeahead form input.




    0 comments:

    Post a Comment

    Popular Posts

    Labels

    Archive

     

    Blogroll

    Recepies

    Flickr Images

    Copyright © 2014. Tutorials Blog - All Rights Reserved