Typeahead not sending requests to server - ruby-on-rails

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.

Related

Unable to reset/update options on jQuery Chosen in rails app

I'm developing a rails 5.1 app. I'm using chosen javascript plugin in my app for making the select-boxes more user friendly.
In one of my viewpage, I have 2 chosen select boxes. one for project and other for tasks. Requirement is to load only the associated tasks on change of project select box.
My View
<div class="form-group pad-right-one">
<%= f.collection_select :task_project_id_eq, #projects.order(:number), :id, :project_with_number, { include_blank: 'Project' }, {class: 'chosen-select', onchange: "populateTaskFieldWithOptions()"} %>
</div>
<div class="form-group pad-right-one">
<%= f.collection_select :task_id_eq, #tasks.order(:project_id, :number), :id, :task_with_number, { include_blank: 'Task' }, {class: 'chosen-select'} %>
</div>
Js Code
Ajax call that I'm making is a success and I'm getting all the values.
function populateTaskFieldWithOptions(){
let projectId = $("#q_task_project_id_eq").val();
$.ajax({
type: "POST",
url: "/mail/getTasks",
data: {project: projectId},
success:
function(result){
console.log("---Ajax Success----");
document.getElementById('q_task_id_eq').selectedIndex = -1;
var newOption = $('<option value="1">test</option>');
$('#q_task_id_eq').append(newOption);
$('#q_task_id_eq').trigger("chosen:updated");
// Other options I tried ...
//$('#q_task_id_eq').trigger("liszt:updated");
//$('#q_task_id_eq').val(' ').trigger('liszt:updated');
//$('#q_task_id_eq').val(' ').trigger('chosen:updated');
},
error:
function(jqXHR, textStatus, errorThrown){
console.log("---Ajax Error----")
console.error('AJAX Error: ' + textStatus + errorThrown);
}
})
};
I'm not able to reset or update the chosen dropdown.
Any help is really appreciated. Thanks in advance.
$(".chosen-select").chosen("destroy");

Ajax call on a <select> in a formtastic form

I need in my app to select from a list of provider a provider, and then, via ajax, I could see below a list of categories, that belongs to a specific provider. I have a form in activeadmin:
<%= semantic_form_for [:admin, #game], builder: ActiveAdmin::FormBuilder do |f| %>
<%= f.semantic_errors :state %>
<%= f.inputs do %>
<%= f.input :categorization_id, label: 'Provider', as: :select,
collection: Provider.all.map { |provider| ["#{provider.name}", provider.id] },
input_html: { class: (:provider_select), 'data-url': category_select_path(provider: 4) } %>
<%= f.input :categorization_id, label: 'Category',input_html: { class: ('category_dropdown') }, as: :select,
collection: Category.all.map { |category| ["#{category.name}", category.id]}%>
...
<% end %>
<%= f.actions %>
<% end %>
In activeadmin controller I have:
controller do
def ajax_call
#provider = Provider.find(params[:provider])
#categories = #provider.categories
respond_to do |format|
format.json { render json: #categories }
end
end
end
JS:
$(document).on('ready page:load', function () {
$('.select.input.optional').last().addClass('hidden_row');
$('#game_categorization_id').change(function () {
var id_value = this.value;
$('.hidden_row').removeClass('hidden_row');
$.ajax({
type: 'GET',
url: '/admin/games/category_select'
// data: id_value
})
});
});
And the routes: match '/admin/games/category_select' => 'admin/games#ajax_call', via: :get, as: 'category_select'
I don't have an idea, how can I pass providers id from collection into url. Currently, I have there category_select_path(provider: 4), but actually it has to be smth. like this - category_select_path(provider: provider.id) In the browser, in a Network tab of devtools I can see my category_select, but there is an error: Couldn't find Game with 'id'=category_select. I can't figure out from where does it come. Any suggestions? Thanks.
The problem was in routes: match '/admin/games/category_select' => 'admin/games#ajax_call', via: :get, as: 'category_select'. It is reserved by a show action of Activeadmin controller. So I changed my routes to: get '/admin/select_category' => 'admin/games#get_providers_categories', as: 'select_category', and added to ajax call data: {provider: provider}, so I could fire in params id of provider:
$.ajax({
type: 'GET',
url: '/admin/select_category',
data: {
provider: provider
},
success: (function (data) {
$('#select_category').children('option').remove();
$('#select_category').prepend('<option value=""></option>');
$.each(data.categories, function () {
$('#select_category').append('<option value="' + this.id + '">' + this.name + '</option>')
})
})
})

simple_form select collection populated by AJAX call

In my view I have a simple form with two select lists:
<%= simple_form_for #job, url: jobs_path do |f| %>
<%= f.input_field :types, as: :select, collection: #types, id 'types-select' %>
<%= f.input_field :subtypes, as: :select, collection: #subtypes %>
<% end %>
When a user selects an option from the first list, the second list below should be populated with values from the database based on the above selection.
For this reason, I am making ajax request when a user selects an option from the first list:
$('#types-select').change(function(){
$.ajax({
url: '/subtypes',
dataType: 'json',
type: 'GET',
data: {
type_id: this.value
},
success: function(data) {
console.log(data);
}
});
});
Controller looks like this:
class SubtypesController < ApplicationController
respond_to :json
def index
#subtypes = Type.find(params[:type_id]).subtypes
render json: #subtypes
end
end
At this point how can I fill up the second select with options from #subtypes?
You can populate second dropdown within success callback. Make sure #subtypes is returned in proper json format too.
Controller:
def index
#subtypes = Type.find(params[:type_id]).subtypes
render json: #subtypes.map { |item| { value: item.value } }
end
JS:
$.ajax({
url: '/subtypes',
dataType: 'json',
type: 'GET',
data: {
type_id: this.value
},
success: function(data) {
// Populate second dropdown here
var output = '';
$subtypes.empty().append(function() {
data.forEach(function(item) {
output += "<option>" + item.value + "</option>"
});
return ouput;
});
}
});

Typeahead with 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.

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

Resources