I am using the Typeahead.js plugin. I am trying to create custom templates for the suggestions. Currently, I have the following:
var suggestions = new Bloodhound({
datumTokenizer: Bloodhound.tokenizers.obj.whitespace('value'),
queryTokenizer: Bloodhound.tokenizers.whitespace,
remote: '/api/suggests?querytext=%QUERY'
});
suggestions.initialize();
$(document).ready(function() {
$('input.typeahead').typeahead(
{ minLength: 3 },
{
name: 'suggestions',
source: suggestions.ttAdapter(),
templates: {
suggestion: function(data) {
var str = '';
str += '<div>Result: ';
// if suggestion is a Customer show 1 icon and the Name
// elseif suggestion is a Product show a different icon and the name
str += '</div>';
return str;
}
}
}
);
});
The suggestions are popping up. However, I am unable to actually get the property values from inside of my results. When Bloodhound requests the suggestions, I get a result set back that looks like this:
{
"Results":[
{
"Type":"Customer",
"Id":5,
"Name":"Bill",
"LastUpdated":"01-01-2015"
},
{
"Type":"Customer",
"Id":135,
"Name":"Billows",
"LastUpdated":"01-02-2015",
},
{
"Type":"Product",
"Id":241,
"Name":"Bill Check",
"LastUpdate":"01-04-2015"
}
],
"TotalResults":3,
"TotalCustomers":2,
"TotalProducts":1
}
How do I get the individual Name and Type values for a single suggestion in the template so I can render it properly?
Thank you!
Try this
var suggestions = new Bloodhound({
datumTokenizer: Bloodhound.tokenizers.obj.whitespace('value'),
queryTokenizer: Bloodhound.tokenizers.whitespace,
remote: {
url: '/api/suggests?querytext=%QUERY',
filter: function(list) {
var suggestions = list.Results;
return $.map(suggestions, function(suggestion) { return { Type: suggestion.Type, Id: suggestion.Id, Name: suggestion.Name, LastUpdated: suggestion.LastUpdated }; });
}
}
});
suggestions.initialize();
$(document).ready(function () {
$('input.typeahead').typeahead(
{ minLength: 3 },
{
name: 'suggestions',
source: suggestions.ttAdapter(),
templates: {
suggestion: function (data) {
var str = '';
str += '<div>Result: ';
// get value by data.Type data.Name
str += '</div>';
return str;
}
}
}
);
});
Related
Im trying to use bloodhound and typeahead to create an autocomplete. The data is being returned correctly but displayed in the options as undefined
My code is:
Html:
<form class="typeahead" role="search">
<div class="form-group">
<input type="search" name="q" class="form-control search-input" placeholder="Search" autocomplete="off">
</div>
</form>
Javascript:
var engine = new Bloodhound({
remote: {
url: '{{ route('search') }}?query=%QUERY',
wildcard: '%QUERY'
},
datumTokenizer: Bloodhound.tokenizers.whitespace('name'),
queryTokenizer: Bloodhound.tokenizers.whitespace
});
$(".search-input").typeahead({
hint: true,
highlight: true,
minLength: 1
}, {
source: engine.ttAdapter(),
// This will be appended to "tt-dataset-" to form the class name of the suggestion menu.
name: 'profileList',
// the key from the array we want to display (name,slug...)
templates: {
empty: [
'<div class="list-group search-results-dropdown"><div class="list-group-item">Nothing found.</div></div>'
],
header: [
'<div class="list-group search-results-dropdown">'
],
suggestion: function (data) {
var profile = [];
profile.push(data);
console.log(profile);
return '' + data.name + ''
}
}
});
When I console.log(data) I get 2 results which look like this:
Hello Molly
hello-molly-436057803095647
but the values are displayed as undefined. The data returned from the backend looks like:
{"name":"Hello Molly","slug":"hello-molly-436057803095647"}
I want to display name and slug like this: return '' + data.name + '' as a suggestion. How can I do that?
For anyone else that gets stuck I had to create a transform function:
transform: function(response) {
return $.map(response, function (profile) {
return {
name: profile.name,
slug: profile.slug
}
});
},
to map out the json response. Also if your using a lot of browser caching clear your cache as this can stop the javascript from updating.
Full code:
var engine = new Bloodhound({
remote: {
url: '{{ route('search') }}?query=%QUERY',
wildcard: '%QUERY',
transform: function(response) {
return $.map(response, function (profile) {
return {
name: profile.name,
slug: profile.slug
}
});
},
},
datumTokenizer: Bloodhound.tokenizers.whitespace('name', 'slug'),
queryTokenizer: Bloodhound.tokenizers.whitespace
});
engine.initialize();
$(".search-input").typeahead({
hint: true,
highlight: true,
minLength: 1,
displayKey: 'name',
}, {
source: engine.ttAdapter(),
// This will be appended to "tt-dataset-" to form the class name of the suggestion menu.
name: 'profileList',
// the key from the array we want to display (name,id,email,etc...)
templates: {
empty: [
'<div class="list-group search-results-dropdown"><div class="list-group-item">Nothing found.</div></div>'
],
header: [
'<div class="list-group search-results-dropdown">'
],
suggestion: function (data) {
return '' + data.name + ''
}
}
});
I am trying to do a form with autocomplete. When a user type a part of a name typeahead suggests people that are in our database. If the user selects one of the suggestion I want to the full form to be filled from the autosuggestion.
Everything works but all my attempts to assign to the data object the value from the suggestion. When I log the this.newReviewer I get this is undefined... here is my code:
var Vue = require('vue')
var validator = require('vue-validator')
var resource = require('vue-resource')
Vue.use(validator)
Vue.use(resource)
var token = $('#token').attr('value');
Vue.http.headers.common['X-CSRF-TOKEN'] = token;
new Vue({
el:'#invite',
data: {
newReviewer: {
title:'',
last_name:'',
first_name:'',
email:'',
ers_id:'null'
},
reviewers: {},
quantity: {},
submitted: false,
},
ready: function(){
this.fetchInvitedReviewers();
console.log(this.newReviewer);
var ersContacts = new Bloodhound({
datumTokenizer: Bloodhound.tokenizers.obj.whitespace('value'),
queryTokenizer: Bloodhound.tokenizers.whitespace,
remote: {
url: 'api/search/%QUERY',
wildcard: '%QUERY'
}
});
$('#last_name')
.typeahead({
minLength: 2,
highlight: true,
hint: true
},
{
displayKey: 'last_name',
templates: {
suggestion: function(ersContacts) {
return (
'<div>' +
'<h3>'
+ ersContacts.title + ' '
+ ersContacts.first_name + ' '
+ ersContacts.last_name
+ '</h3>'
+ '<p class="uk-text-muted">'
+ ersContacts.city + ' '
+ ersContacts.country
+ '</p>' +
'</div>'
)
}
},
source: ersContacts
})
.on('typeahead:select', function(e, suggestion){
console.log(this.newReviewer);
this.newReviewer.last_name.push(suggestion.last_name);
this.newReviewer.email.push(suggestion.email);
})
.bind(this);
},
computed:{
//errors: function() {
// for(var key in this.newReviewer) {
// if (! this.newReviewer[key]) return true;
// }
// return false;
//}
},
methods: {
fetchInvitedReviewers: function() {
this.$http.get('api', function(response) {
this.$set('reviewers', response.reviewers);
this.$set('quantity', response.quantity);
});
},
onSubmitForm: function(e){
e.preventDefault();
var reviewer = this.newReviewer;
//add new reviewer to reviewers array
this.reviewers.push(reviewer);
//reset input values
this.newReviewer = {title:'', last_name: '', first_name: '', email:'', ers_id:''}
//substract one to the quantity
this.quantity -= 1 ;
//sent post ajax request
this.$http.post('api/store', reviewer)
//show success and count how many left
if(this.quantity <= 0) {
this.submitted = true;
}
}
},
validator: {
validates: {
email: function (val) {
return /^(([^<>()[\]\\.,;:\s#\"]+(\.[^<>()[\]\\.,;:\s#\"]+)*)|(\".+\"))#((\[[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\])|(([a-zA-Z\-0-9]+\.)+[a-zA-Z]{2,}))$/.test(val)
}
}
}
});
found...
Sorry guys. this
})
.bind(this);
should have been
}
.bind(this));
After long struggles with Twitters typeahead.js, I'm finally at the point where I get to decide which template I should use for my suggestions.
But although this would seem like a straight-forward procedure, I get the following error:
Uncaught TypeError: g.templates.suggestion is not a function
My code looks like this
HTML:
<input id = "search" type="text" placeholder="Colors">
Javascript:
var colors = ["red", "blue", "green", "yellow", "brown", "black"];
var colorsource = new Bloodhound({
datumTokenizer: Bloodhound.tokenizers.whitespace,
queryTokenizer: Bloodhound.tokenizers.whitespace,
// `states` is an array of state names defined in "The Basics"
local: colors
});
$('#search').typeahead({
hint: true,
highlight: true,
minLength: 1
},
{
name: 'color',
source: colorsource,
templates: {
empty: [
'<div class="empty-message">',
'unable to find any Best Picture winners that match the current query',
'</div>'
].join('\n'),
suggestion: '<div>{{color}}</div>'
}
});
I've seen examples where Handlebars.js is being used to compile the template, but I'm planning on using variables from Angular.js in my suggestions, so I don't want to do that.
Any suggestions on how this problem can be solved would be appreciated.
You suggestion options must be a function that returns the HTML, e.g.
...
suggestion: function(e) { return ('<div>' + e.value + '</div>'); }
...
I am following #potatopeelings but the suggestions not appear.
Here is my code
$(document).ready(function () {
$("#penilai").typeahead({
source: function (query, process) {
var countries = [];
map = {};
return $.post('/Evaluation/JsonSenaraiPenilai', { query: query }, function (data) {
$.each(data, function (i, country) {
map[country.Evaluator_name] = country;
countries.push(country.Evaluator_name);
});
process(countries);
});
},
templates: {
empty: [
'<div class="empty-message">',
'unable to find any Best Picture winners that match the current query',
'</div>'
].join('\n'),
suggestion: function (e) { return ('<div>' + e.Evaluator_name + '-' + e.Evalator_staf_no + '</div>'); }
},
updater: function (item) {
var selectedShortCode = map[item].Evalator_staf_no;
$("#evalutor").val(selectedShortCode);
return item;
}
});
});
i am current using this plugin for tags-input 'bootstrap-tagsinput'
i am trying to use the typeahead feature provided by this plugin.
the source attribute in typeahead expects a promise to be returned.but i need to modify the returned data. How do i do this?
$('input').tagsinput({
typeahead: {
source: function(query) {
return $.get('/tags.json').then(function(data){
return _.pluck(data.tags,'keyword');
});
}
}
});
Try
var list = ["Amsterdam", "Beijing", "Cairo"];
var citynames = new Bloodhound({
datumTokenizer: Bloodhound.tokenizers.obj.whitespace('name'),
queryTokenizer: Bloodhound.tokenizers.whitespace,
prefetch: {
url: '/tags.json',
filter: function (res) {
// modify returned data here ,
// e.g., `res` : `["abc"]`
return $.map(res[0].split(""), function (val, i) {
return {
name: val.toUpperCase() === list[i][0] ? list[i] : null
};
});
}
}
});
citynames.initialize();
$('input.bootstrap-tagsinput').tagsinput({
typeaheadjs: {
name: 'citynames',
displayKey: 'name',
valueKey: 'name',
source: citynames.ttAdapter()
}
});
jsfiddle http://jsfiddle.net/guest271314/dbfx1tso/
See Bootstrap Tags Input Typeahead
So I want to use typehead.js to have an autocomplete field (http://twitter.github.io/typeahead.js/) :
$(document).ready(function() {
var result;
var result = new Bloodhound({
datumTokenizer: function(d) { return Bloodhound.tokenizers.whitespace(d.Domain.domain); },
queryTokenizer: Bloodhound.tokenizers.whitespace,
limit: 10,
prefetch: {
url: 'data.json'
}
});
result.initialize();
$('.example-twitter-oss .typeahead').typeahead(null, {
name: 'twitter-oss',
displayKey: 'Domain.domain',
source: result.ttAdapter(),
templates: {
suggestion: Handlebars.compile([
'<p class="repo-language">Class {{Domain.class}}</p>',
'<p class="repo-name"><img src="http://www.google.com/s2/favicons?domain={{Domain.domain}}" alt=""> {{Domain.domain}}</p>',
'<p class="repo-description">{{Domain.company}}</p>'
].join(''))
}
});
});
This is my data source :
[
{
"Domain":{
"domain":"duckduckgo.com",
"company":"DuckDuckGo, Inc.",
"category":"0"
}
},
{
"Domain":{
"domain":"twitter.com",
"company":"Twitter, Inc.",
"category":"0"
}
},
{
"Domain":{
"domain":"apple.com",
"company":"Apple, Inc.",
"category":"0"
}
}
]
It seems that the dropdown menu works fine, but the input field does not have the prediction displaying (I mean it you start typing "Twi" it does not display in grey "tter" ).
Any idea on how to solve this ?
Your display key is incorrect. typeahead.js will not parse your key and know that it needs to access a nested object. Instead, in order to achieve the functionality you want, do the following:
$('.example-twitter-oss .typeahead').typeahead(null, {
// ...
displayKey: function(o) { return o.Domain.domain; }
// ...
});