web-dev-qa-db-fra.com

Utilisez une valeur différente des données JSON au lieu de displayKey à l'aide de Typeahead

J'ai commencé à utiliser Typeahead.js et je ne parviens pas à trouver un moyen de permettre à un utilisateur de taper et de rechercher un nom de société. Une fois sélectionné, entrez le code de société associé. 

Fichier .json:

[{
    "company_name": "Facebook",
    "code": "fb",
}, {
    "company_name": "Google",
    "code": "goog",
}, {
    "company_name": "Yahoo",
    "code": "yhoo",
}, {
    "company_name": "Apple",
    "code": "aapl",
}, {
    "company_name": "Royal Mail",
    "code": "rmg.l",
}]

.js Script:

var stocks = new Bloodhound({
    datumTokenizer: function(d) {
        return Bloodhound.tokenizers.whitespace(d.code);
    },
    queryTokenizer: Bloodhound.tokenizers.whitespace,
    limit: 3,
    prefetch: {
        url: 'javascripts/stockCodes.json',
        filter: function(list) {
            return $.map(list, function(stock) {
                return {
                    code: stock
                };
            });
        }
    }
});

stocks.initialize();

$('.typeahead').typeahead(null, {
    name: 'stocks',
    displayKey: 'code',
    source: stocks.ttAdapter()
});

Actuellement, cela n’affiche que la liste des codes lorsque l’utilisateur tape dans le champ de saisie. Cependant, j'aimerais savoir s'il existe un moyen de leur permettre d'effectuer une recherche sur code mais une fois sélectionnée, la valeur dans la zone de texte doit être company_name? Est-ce même possible en utilisant ce plugin. Toute aide est la bienvenue. 

Merci!

29
user1779796

displayKey est utilisé pour indiquer quelle clé doit être affichée dans la liste déroulante et dans le champ de saisie après que l'utilisateur a sélectionné une entrée.

Si vous souhaitez que les entrées figurant dans la liste déroulante soient différentes de celles qui se retrouvent dans le champ de saisie, vous devez utiliser un modèle personnalisé.

De la documentation :

suggestion - Utilisé pour rendre une seule suggestion. Si défini, cela doit être un modèle précompilé. L'objet de suggestion associé servira de le contexte. La valeur par défaut de displayKey est encapsulée dans une balise p i.e . <p>{{value}}</p>.

Quelque chose comme ça devrait marcher:

$('.typeahead').typeahead(null, {
    name: 'stocks',
    displayKey: 'company_name',
    source: stocks.ttAdapter(),
    templates: {
        suggestion: function (stock) {
            return '<p>' + stock.code + '</p>';
        }
    }
});

Le modèle soumis sera utilisé pour afficher stock.code dans la liste déroulante, tandis que stock.company_name sera affiché dans le champ de saisie une fois que l'utilisateur aura sélectionné une entrée.

32
Esseb

Je ne suis pas jQuery/JavaScript-Guru. Je préfère donc la solution de facilité. Juste pour comprendre ce que j'ai fait quand je regarde mon code plus tard ...

Grâce à Eric Saupe j'ai trouvé une solution intelligente:

//JSON FILE
[
    {
        "company_name": "Facebook",
        "code": "fb",
    },
    {
        "company_name": "Google",
        "code": "goog",
    },
    {
        "company_name": "Yahoo",
        "code": "yhoo",
    },
    {
        "company_name": "Apple",
        "code": "aapl",
    },
    {
        "company_name": "Royal Mail",
        "code": "rmg.l",
    },
 ]

// JS SCRIPT

   var stocks = new Bloodhound({
        datumTokenizer: Bloodhound.tokenizers.obj.whitespace('company_name'),
        queryTokenizer: Bloodhound.tokenizers.whitespace,
        remote: 'javascripts/stockCodes.json'
    });

    stocks.initialize();

    $('.typeahead').typeahead(
        null, {
        name: 'stocks',
        displayKey: 'company_name',
        source: stocks.ttAdapter()
    }).on('typeahead:selected', function(event, data){            
        $('.typeahead').val(data.code);        
    });

Utilisez simplement les événements personnalisés typeahead tels que décrits dans les docs sur github .

J'espère que ça aide (et quand c'est juste pour ma propre référence ultérieure).

JSFIDDLE

18
Tobse

Vous devez utiliser la variable ´displayKey´. Voir ci-dessous copier-coller à partir de la dactylographie:

displayKey - Pour un objet de suggestion donné, détermine la représentation sous forme de chaîne de celui-ci. Ceci sera utilisé lors du réglage de la valeur du contrôle d'entrée après la sélection d'une suggestion. Peut être une chaîne de clé ou une fonction qui transforme un objet de suggestion en chaîne. La valeur par défaut est value.

https://github.com/Twitter/typeahead.js/blob/master/doc/jquery_typeahead.md

Votre code spécifique ressemblerait alors à ceci:

var stocks = new Bloodhound({
        datumTokenizer: function(d) { return Bloodhound.tokenizers.whitespace(d.code); },
        queryTokenizer: Bloodhound.tokenizers.whitespace,
        limit: 3,
        prefetch: {
            url: 'javascripts/stockCodes.json',
            filter: function(list) {
                // This should not be required, but I have left it incase you still need some sort of filtering on your server response
                return $.map(list, function(stock) { return { code: stock.code, company_name: stock.company_name }; });
            }
        }
    });

    stocks.initialize();

    $('.typeahead').typeahead(null, {
        name: 'stocks',
        displayKey: function(stock) {
           return stock.company_name;
        },
        source: stocks.ttAdapter()
    });

J'avais une exigence très similaire sur mon propre site, et cela fonctionnait sans problème. Je n'ai cependant pas essayé cet exemple particulier, alors laissez-moi savoir si cela fonctionne.

N'oubliez pas d'appeler stocks.clearPrefetchCache(); pour vider votre cache afin de faciliter le suivi des bogues.

5
bblue

Si je lis correctement, je crois que c'est ce que vous voulez:

var stocksData = [{
    "Facebook": "fb",
}, {
    "Google": "goog",
}, {
    "Yahoo": "yhoo",
}, {
    "Apple": "aapl",
}, {
    "Royal Mail": "rmg.l",
}, ];

var stocks = new Bloodhound({
    datumTokenizer: function (d) {
                  for (var prop in d) {
                      return Bloodhound.tokenizers.whitespace(d[prop]);
                  }

    },
    queryTokenizer: Bloodhound.tokenizers.whitespace,
    limit: 3,
    local: stocksData,
});

stocks.initialize();

$('input').typeahead(null, {
    name: 'stocks',
    displayKey: function(stocks) {
        for (var prop in stocks) {
            return prop;    
        }
    },
    source: stocks.ttAdapter()
});

Vous voudrez bien sûr changer le local en prefetch/remote comme vous l'avez fait pour le fichier json.

METTRE &AGRAVE; JOUR

VIOLON

4
Tomanow

Ajoutez la valeur à afficher dans le paramètre display :

$(".comp-search").typeahead({
    hint: true,
    highlight: true,
    minLength: 1,
    displayKey: 'company_name',
}, {
    source: engine.ttAdapter(),
    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 '<a href="javascript:void(0);" class="list-group-item">' + data.company_name + '</a>';
        }
    },
    display: function(data) { return data.company_name; }
});

J'espère que c'est utile

0
ArtisanBay

Avait le même problème, ne pouvait pas le faire fonctionner avec la propriété display ou displayKey. Nous y avons travaillé en ajoutant la propriété name aux objets source:

            $.each(stocks, function (i, item) {
                item.name = item.company_name;
            });
0
marco