jquery - react - typeahead scrollable
Typeahead v0.10.2 & Bloodhound-Trabajando con objetos JSON anidados (2)
ACTUALIZAR
Basado en la respuesta correcta de @BenSmith ( https://stackoverflow.com/users/203371/BenSmith ) pude encontrar mi problema y descubrí que no estaba navegando a través de mi jerarquía JSON correctamente. Aquí está el código de trabajo:
// instantiate the bloodhound suggestion engine
var engine = new Bloodhound({
datumTokenizer: function (datum) {
return Bloodhound.tokenizers.whitespace(datum.title);
},
queryTokenizer: Bloodhound.tokenizers.whitespace,
prefetch: {
url: "SampleData.json",
filter: function (data) {
//console.log("data", data.response.songs)
return $.map(data.response.songs, function (song) {
return {
title: song.title,
artistName: song.artist_name
};
});
}
}
});
// initialize the bloodhound suggestion engine
engine.initialize();
// instantiate the typeahead UI
$(''#prefetch .typeahead'').typeahead(
{
hint: true,
highlight: true,
minLength: 1
},
{
name: ''engine'',
displayKey: ''title'',
source: engine.ttAdapter(),
templates: {
empty: [
''<div class="empty-message">'',
''unable to find any results that match the current query'',
''</div>''
].join(''/n''),
suggestion: Handlebars.compile(''<p><strong>{{title}}</strong> by {{artistName}}</p>'')
}
});
Gracias @BenSmith por la ayuda!
Pregunta original
Soy nuevo en el trabajo con Typeahead y Bloodhound. La documentación no es muy útil. Tengo un conjunto de objetos JSON que recibo de una API con la que estoy trabajando. Estoy tratando de averiguar cómo navegar a través de mis objetos JSON para que Bloodhound pueda entenderlos.
El objetivo aquí es que un usuario comience a escribir el nombre de una canción. El autocompletado mostrará una lista de nombres de canciones y el artista con el que fue interpretada.
Por ejemplo: Chimes At Midnight by Mastodon
Estoy usando las últimas versiones de cada biblioteca: https://twitter.github.io/typeahead.js/
El JSON de muestra (SampleData.json):
{"response": {"status": {"version": "4.2", "code": 0, "message": "Success"}, "songs": [{"title": "Chimes At Midnight", "artist_name": "Mastodon", "artist_foreign_ids": [{"catalog": "7digital-AU", "foreign_id": "7digital-AU:artist:29785"}, {"catalog": "7digital-UK", "foreign_id": "7digital-UK:artist:29785"}], "tracks": [], "artist_id": "ARMQHX71187B9890D3", "id": "SOKSFNN1463B7E4B1E"}, {"title": "Down Under", "artist_name": "Men at Work", "artist_foreign_ids": [{"catalog": "7digital-AU", "foreign_id": "7digital-AU:artist:50611"}], "tracks": [], "artist_id": "AR4MVC71187B9AEAB3", "id": "SORNNEB133A920BF86"}]}}
Utilice este sitio http://json.parser.online.fr/ para formatear el JSON fácilmente.
El JSON que recibiré siempre estará en el mismo formato, pero contendrá datos diferentes. En este ejemplo, las "pistas" son nulas. Otros resultados tendrán datos. También necesitaría poder acceder a esos datos también.
Estoy usando la última versión de JQuery. Esto es lo que he incluido en mi página html:
<script src="Scripts/jquery-2.1.1.min.js"></script>
<script src="Scripts/typeahead.bundle.min.js"></script>
Aquí está el HTML:
<div id="prefetch">
<input class="typeahead" type="text" placeholder="Songs...">
</div>
Aquí está el guión:
// instantiate the bloodhound suggestion engine
var engine = new Bloodhound({
datumTokenizer: function (d) { return Bloodhound.tokenizers.whitespace(d.tokens.join('' '')); },
queryTokenizer: Bloodhound.tokenizers.whitespace,
prefetch: {
url: "SampleData.json",
filter: function (response) {
return response.engine;
}
}
});
// initialize the bloodhound suggestion engine
engine.initialize();
// instantiate the typeahead UI
$(''#prefetch .typeahead'').typeahead(
{
hint: true,
highlight: true,
minLength: 1
},
{
name: ''songs'',
displayKey: function (engine) {
return engine.songs.artist_name;
},
source: engine.ttAdapter()
});
Cuando intento ejecutar este código, aparece el siguiente error:
No se detectó TypeError: no se puede leer la propiedad ''tokens'' de undefined
Cualquier ayuda o dirección aquí sería muy apreciada. Solo necesito saber cómo obtener los datos JSON con los que trabajo trabajando con Typeahead / Bloodhound.
¡Gracias!
Debe escribir la función de filtro para que cree una matriz de objetos javascript para usar como datos. Lo siguiente debería funcionar (no he probado esto):
filter: function (response) {
return $.map(response.songs, function (song) {
return {
title: song.title,
artistName: song.artist_name
};
});
}
(Un ejemplo de la función de filtro se puede encontrar here )
Y cambia tu datumtokenizer a:
datumTokenizer: function (datum) {
return Bloodhound.tokenizers.whitespace(datum.title);
}
también cambia tu displaykey a:
displayKey: ''title''
Como esta es la clave que Typeahead utilizará para la búsqueda.
En cuanto a mostrar el nombre de la canción y el artista en la lista de sugerencias, le sugiero que use plantillas (por ejemplo, manillares) para mostrar los resultados. Vea el ejemplo de "Plantilla personalizada" en la página de ejemplos de Typeahead . Su marca de sugerencia se verá similar a la siguiente:
suggestion: Handlebars.compile(''<p><strong>{{title}}</strong> by {{artistName}}</p>'')
Mi respuesta no es nada nuevo, solo una actualización para v0.11 de typeahead de twitter. Como siempre, redirige tus votos positivos (si los hay) a la respuesta original.
Un recordatorio amistoso para todos los que todavía están usando Twitter-Typeahead es alejarse de este repositorio ya que ya no se mantiene. En su lugar, corejavascript/typeahead.js a corejavascript/typeahead.js que es una bifurcación del repositorio original, y el mismo autor (@JakeHarding) mantiene este repositorio.
De v0.10 a v0.11, algunas cosas han cambiado, y también la respuesta. Aquí está mi nuevo código para esta nueva versión.
HTML
<div id="prefetch">
<input class="typeahead" type="text" placeholder="Countries">
</div>
JS
var tags = new Bloodhound({
datumTokenizer: function(datum) {
return Bloodhound.tokenizers.whitespace(datum.name);
},
queryTokenizer: Bloodhound.tokenizers.whitespace,
prefetch: {
url: ''http://www.yourwebsite.com/js/data.json'',
cache: false,
transform: function(response) {
return $.map(response, function (tag) {
return {
name: tag.tagName,
id: tag.tagId
}
});
}
}
});
$(''#prefetch .typeahead'').typeahead({
minLength: 3,
highlight: true
}, {
name: ''tags-dataset'',
source: tags,
display: ''name''
});
Que ha cambiado:
- No hay opción de
filter
enprefetch
. En su lugar tienes que usartransform
. -
displayKey
undertypeahead()
se ha cambiado paradisplay
simplemente. -
cache
opción decache
bajotransform
se establece en falso para que la fuente de datos se cargue cada vez Esto es bueno para las pruebas, pero en el servidor de producción, esta opción debe desactivarse si se requiere el almacenamiento en caché de datos.
Como una nota adicional para las personas que están probando este ejemplo con diferentes fuentes de datos con el
cache
establecido en verdadero. Siempre debe ejecutarwindow.localStorage.clear();
Método en su consola para borrar el almacenamiento local ya existente para que se puedan recuperar nuevos datos. Si no lo hace, los datos antiguos se utilizarán y podría pensar por qué su código no funciona.
Aquí hay un ejemplo de JSFIDDLE para que puedas comenzar. Algunos puntos a tener en cuenta:
- No sabía si hay un CDN para typeahead, así que simplemente pegué todo el código javascript de typeahead allí. En la parte inferior de la página, puedes ver mi función.
- La fuente de datos apunta a un enlace que es un archivo alojado en mi cuenta de Dropbox. En caso de que elimine este archivo, este ejemplo no funcionaría en absoluto. Por lo tanto, necesita proporcionar su propia fuente. Aquí está el contenido de ese archivo -
[{"tagId":9,"tagName":"Action"},{"tagId":10,"tagName":"Adventure"},{"tagId":6,"tagName":"Books"},{"tagId":11,"tagName":"Fantasy"},{"tagId":2,"tagName":"Games"},{"tagId":1,"tagName":"Movies"},{"tagId":3,"tagName":"Music"},{"tagId":8,"tagName":"News"},{"tagId":4,"tagName":"Office"},{"tagId":5,"tagName":"Security"},{"tagId":7,"tagName":"TV-Shows"}]