Typeahead with rails - ruby-on-rails

I am trying to implement twitter typeahead with rails.
I have done this using searchkick gem and elasticsearch.
There is a slight issue in here,my remote call of BloodHound is like this
var engine = new Bloodhound({
datumTokenizer: function(d) {
console.log(d);
return Bloodhound.tokenizers.whitespace(d.username);
},
queryTokenizer: Bloodhound.tokenizers.whitespace,
remote: {
url: "../users/autocomplete?query=%QUERY"
}
});
Now in here instead of the %QUERY getting substituted with the value of typeahead search box,it just gives the string %QUERY as it is.
Rest everything is working fine because if I goto the url
http://localhost:3000/users/autocomplete?query=vive
I get the desired results.
Its just that the %QUERY is not getting substituted.
Here is the form
<%= form_tag users_path, class:'ui form',method: :get do %>
<div class="ui small icon input">
<%= text_field_tag :query, params[:query],class:'typeahead',id:'user_search',placeholder:'Search Breeder' %>
<i class="search icon"></i>
</div>
<%end%>
And the controller
def autocomplete
render json: User.search(params[:query],autocomplete:true).map{|user| {username:user.username,value:user.id}}
end
/routes.rb/
resources :users do
collection do
get :autocomplete
end
end
Can someone please help.

Alright after struggling a lot to find an answer to this,I somehow got it working.
So for anyone who is stuck at the same place,here is the solution:
var engine = new Bloodhound({
datumTokenizer: function(d) {
console.log(d);
return Bloodhound.tokenizers.whitespace(d.username);
},
queryTokenizer: Bloodhound.tokenizers.whitespace,
remote: {
url: "../users/autocomplete?query=%QUERY",
//add wildcard to make it work
wildcard:"%QUERY"
}
});
Hope it helps someone.

Related

using the city-state gem in rails

Hey guys im currently working on a devise sign up form, the end goal is a user can select a state from the united states and a select tag below will populate with the correct cities in that state. im using the city-state gem. https://github.com/loureirorg/city-state
ive looked at other examples like this one https://forum.upcase.com/t/dependent-country-city-state/7038 my code is below
routes.rb
resources :states, only: :new
registrations.new.html.erb
<div class="field">
<%= f.select :state, options_for_select(CS.states(:us)), {:prompt => "State"}, {:class => "signup-input-container--input", :id => "state-picker"} %>
</div>
<div class="field">
<%= f.select :city, options_for_select([]),{}, {:class => "signup-input-container--input", :id => "city-picker"} %>
</div>
main.js
document.addEventListener("turbolinks:load", function(){
var state = document.getElementById("state-picker");
state.addEventListener("change", function() {
Rails.ajax({
url: "/states?country=" + "United States" + "&state=" +
state.value,
type: "GET"
})
})
});
registrations-controller.erb
def new
super
#cities = CS.get(:us, params[:state])
end
new.js.erb
var city = document.getElementById("city-picker");
while (city.firstChild) city.removeChild(city.firstChild);
var placeholder = document.createElement("option");
placeholder.text = "Choose a city";
placeholder.value = "";
city.appendChild(placeholder);
<% #cities.each do |c| %>
city.options[city.options.length] = new Option('<%= c %>');
<% end %>
im trying to get this to work the way the example link shows. the only difference is that users will only choose states from the US and citys
From our discussion in the comments the issue appears to be that you are requesting the wrong URL for your cities.
You have a route at /states/new but are making the request to /states. Try updating your main.js to:
document.addEventListener("turbolinks:load", function(){
var state = document.getElementById("state-picker");
state.addEventListener("change", function() {
Rails.ajax({
url: "/states/new?state=" + state.value,
type: "GET"
})
})
});
(I removed the country parameter in the URL because you don't seem to be using it, you say you only need this for the US anyway.)
Let me know how you get on with that.

Searchkick + Bloodhound + Typeahead for autocomplete

I am trying to implement a simple autocomplete feature for a single attribute.
Model:
searchkick text_start: [:name],autocomplete: ['name']
After reindexing the behaviour on the Rails console is ok.
2.2.0-p0 :002 >Doctor.search("a", autocomplete: true).map(&:name)
gives the output-
=> ["a", "aa", "aaa", "aaaa"]
After this i added the Autocomplete action to the controller and a new route to the routes.rb file.
Controller:
def autocomplete
console.log("In auto")
render json: Doctor.search(params[:query], autocomplete: false, limit: 10).map(&:name)
end
Routes:
resources :doctors do
collection do
get :autocomplete
end
end
At this point if i simply test the following URL:
http://localhost:3000/doctors/autocomplete?query="a"
Then i get the expected result in the browser:
["a", "aa", "aaa", "aaaa"]
Now adding a search box.
_header.html.erb:
<%= form_tag doctors_path, method: :get do %>
<div class="form-group">
<%= text_field_tag :query, params[:query], class: 'form-control typeahead', autocomplete: "off" %>
<%= submit_tag 'Search', class: 'btn btn-primary' %>
</div>
<% end %>
And finally the Javascript:
var ready;
ready = function() {
var numbers = new Bloodhound({
remote: {url: "/doctors/autocomplete?query=%QUERY"},
datumTokenizer: function(d) {
return Bloodhound.tokenizers.whitespace(d.name); },
queryTokenizer: Bloodhound.tokenizers.whitespace
});
// initialize the bloodhound suggestion engine
var promise = numbers.initialize();
promise
.done(function() { console.log('success!'); })
.fail(function() { console.log('err!'); });
// instantiate the typeahead UI
$( '.typeahead').typeahead(null, {
displayKey: 'name',
source: numbers.ttAdapter()
});
}
$(document).ready(ready);
$(document).on('page:load', ready);
And this is the script tag used:
<script type="text/javascript" src="https://twitter.github.io/typeahead.js/releases/latest/typeahead.bundle.js"></script>
There is no response shown by the search box on typing anything,also there is no error shown on the console of Google Chrome.
You need to return hash in response of your autocomplete action:
def autocomplete
render json: Doctor.search(params[:query], autocomplete: true, limit: 10).map {|doctor| {name: doctor.name, value: doctor.id}}
end

Typeahead not sending requests to server

I followed this tutorial
https://shellycloud.com/blog/2013/10/adding-search-and-autocomplete-to-a-rails-app-with-elasticsearch
and when i type in the text field, i don't see any ajax requests being sent to the server.
(I added the typeahead.js to my assets)
What am i missing?
Here is my code
view:
.col-xs-12.col-sm-12.col-md-12.col-lg-6.col-lg-offset-3
%form#search_form{action: "/drugs/search", method: "get", text: "search", role:"search"}
.input-group
%input.form-control{type: "text", placeholder: "Search", name: "query", id: "drug_search", autocomplete: "off"}
%span.input-group-btn
%button.btn.btn-default{type: "submit"} Search
.panel-group#drug-list
= render #drugs
= will_paginate #drugs, renderer: BootstrapPagination::Rails
controller:
def autocomplete
render json: Drug.search(params[:query], autocomplete: true, limit: 6).map(&:generic_name)
end
js
$ ->
$("#drug_search").typeahead
name: "drug"
remote: "/drugs/autocomplete?query=%QUERY"
There was a slight API change when v0.10.0 was released. Try this:
var drugSource = new Bloodhound({
datumTokenizer: function(d) { return Bloodhound.tokenizers.whitespace(d.num); },
queryTokenizer: Bloodhound.tokenizers.whitespace,
remote: '/drugs/autocomplete?query=%QUERY'
});
drugSource.initialize();
$('#drug_search').typeahead(null, {
name: 'drug',
source: drugSource.ttAdapter()
});
For more details about what changed with the v0.10.0 release, you can refer to the migration guide.

Refresh div with gmaps4rails (AJAX)

I'm using Rails 3.0.9 version, and jquery.
I've been using this gem without a database. It is used only for map display, and display KML file on it. For this I used:
<div id='ajax_map'>
<% #kmlurl="http://mysite/file1.kml" %>
<%= gmaps( :kml => { :data => "[{ url: #{#kmlurl.inspect}}]" } ) %>
</div>
All great shows.
I want to do that after you change the links (# kmlurl), and click on the button, the map updated with this new KML file. I use a separate action js.erb with the following code:
$('#ajax_map').html('<%= #kmlurl="http://mysite/file2.kml" %>'+'<br />'+'<%= gmaps( :kml => { :data => "[{ url: #{#kmlurl.inspect}}]" } ) %>');
But he does not update the DIV. "js.erb" rendered normally, without using the method of gmaps () it normally returns # kmlurl. I tested this same code in the ". Html.erb" in the tags , it loads a new file, but, of course, just when the page loads.
How can I solve this problem?
Solved the problem as follows (in js.erb):
$('#ajax_map').html('<%= escape_javascript( gmaps({:last_map => false}) ) %>');
Gmaps.map = new Gmaps4RailsGoogle();
Gmaps.load_map = function() {
Gmaps.map.map_options.maxZoom = 15;
Gmaps.map.initialize();
Gmaps.map.kml = [{ url: '<%= "#{#kmlurl}" %>'}];
Gmaps.map.create_kml();
Gmaps.map.adjustMapToBounds();
Gmaps.map.callback();
};
Gmaps.loadMaps();
First I would refactor things just a bit.
Say that first bit of code were in your index page. I'd move the setting of #kmlurl into the corresponding controller action:
def index
#kmlurl = "http://mysite/file1.kml"
end
Then (assuming index?) your index view would be simply:
<div id="ajax_map">
<%= gmaps( :kml => { :data => "[{ url: #{#kmlurl}}]" } ) %>
</div>
Then to add a link that will update the map:
<%= link_to 'Other Map', '/othermap', :remote=>true %>
Now you'd create a route in routes.rb:
match '/othermap' => 'foo#othermap'
Then in foo_controller.rb:
def othermap
#kmlurl = "http://mysite/file2.kml"
end
Then create othermap.js.erb:
$('#ajax_map').html(
'<%=
escape_javascript(
gmaps( :kml => { :data => "[{ url: #{#kmlurl}}]" } )
)
%>'
)
That's a quick fix, but what I would REALLY do is strive to make your view code as simple as possible, and do all the real work in the controller. Ideally your view would just be:
<div id="ajax_map">
<%= gmaps( :kml => { :data => #mapdata } ) %>
</div>
set up #mapdata as appropriate in your controller. You've got too much stuff that really belongs in a controller embedded in your view code! Your othermap.js.erb should be equally simplified. i.e.
$('#ajax_map').html('<%= escape_javascript(gmaps( :kml => { :data => #mapdata } ))%>')

Using ajax pagination (will_paginate) for multiple groups of the same model

I have gotten ajax pagination working using mislav-will_paginate with the js found here: https://github.com/mislav/will_paginate/wiki/Ajax-pagination but I have run into a situation that I am not sure how to handle. I have a number of groups (of the same model) and each group has a number of lists that are paginated. I cannot tell which group to load the lists for in the ajax pagination call. This is the code I am using:
function ajaxPagination(){
var container = $(document.body)
if (container) {
container.observe('click', function(e) {
var el = e.element();
if (el.match('.pagination a')) {
new Ajax.Request(el.href, { method: 'get' })
e.stop()
}
})
}
}
<% #groups.each do |group| %>
<% lists = group.lists.paginate(:page => params[:group_page], :per_page => 5) %>
<% lists.each .... %>
<%= will_paginate lists, :params_name => "group_page" %>
<% end %>
You need to improve your JS to know which 'group' you're clicking.
$("#<%= group %>").html("<%= escape_javascript(render("group")) %>");
See: http://railscasts.com/episodes/174-pagination-with-ajax or read it at: http://asciicasts.com/episodes/174-pagination-with-ajax
$('.group').click(function(){
$.ajax({
type: "GET",
url: "/group",
data: { 'group' : $(this).attr('id') }
success: function(data){
alert( "Success" );
}
});
});

Resources