Twitter bootstrap typeahead ajax esempio


280

Sto cercando di trovare un esempio funzionante di dell'elemento typeahead twitter bootstrap che farà una chiamata Ajax per popolare il suo menu a discesa.

Ho un esempio di completamento automatico jquery funzionante che definisce l'URL Ajax e come elaborare la risposta

<script type="text/javascript">
//<![CDATA[
$(document).ready(function() {
    var options = { minChars:3, max:20 };
    $("#runnerquery").autocomplete('./index/runnerfilter/format/html',options).result(
            function(event, data, formatted)
                {
                    window.location = "./runner/index/id/"+data[1];
                }
            );
       ..

Cosa devo modificare per convertirlo nell'esempio typeahead?

<script type="text/javascript">
//<![CDATA[
$(document).ready(function() {
    var options = { source:'/index/runnerfilter/format/html', items:5 };
    $("#runnerquery").typeahead(options).result(
            function(event, data, formatted)
                {
                    window.location = "./runner/index/id/"+data[1];
                }
            );
       ..

Aspetterò che il problema " Aggiungi supporto fonti remote per typeahead " sia risolto.


Per essere più specifici, mi chiedo come le opzioni di completamento automatico e la funzione di gestione dei risultati si associno alle opzioni di textahead? Esiste una serie di funzioni di gestione dei risultati textalert definite che possono essere sovrascritte o sono il metodo denominato ereditato dall'API jquery sottostante.
emeraldjava,

1
Potresti contrassegnare la risposta di Stijn Van Bael come quella corretta adesso? La risposta di bogert funziona solo con versioni non aggiornate di Bootstrap.
Giles Roberts,

Risposte:


302

Modifica: typeahead non è più raggruppato in Bootstrap 3. Dai un'occhiata:

A partire da Bootstrap 2.1.0 fino alla 2.3.2, puoi farlo:

$('.typeahead').typeahead({
    source: function (query, process) {
        return $.get('/typeahead', { query: query }, function (data) {
            return process(data.options);
        });
    }
});

Per utilizzare i dati JSON in questo modo:

{
    "options": [
        "Option 1",
        "Option 2",
        "Option 3",
        "Option 4",
        "Option 5"
    ]
}

Nota che i dati JSON devono essere del giusto tipo mime (application / json), quindi jQuery lo riconosce come JSON.


3
Come nel fork di Typeahead, i dati devono essere una matrice di stringhe JSON e il tipo di contenuto deve essere application / json.
Stijn Van Bael,

9
2.1 può usare json che non è solo un array di stringhe? Ho bisogno di un valore per l'utente e utilizzare un ID per eseguire ulteriori elaborazioni. È possibile senza prendere una forchetta personalizzata?
Anton

2
@Stijin Ci sono esempi di come quella funzione anonima sarebbe utilizzata qui, per elaborare un ID per un'opzione visualizzata? Grazie!
Acyra,

1
Vorrei sottolineare che l'utilizzo di questo metodo comporta la creazione di un AJAX chiamato per ogni sequenza di tasti sull'input. Se il server sta restituendo essenzialmente dati statici (ovvero non sta realmente facendo nulla con la query), ciò può essere abbastanza dispendioso.
Dologan,

2
perché usare getinvece di getJSON? Sembra più appropriato.
greg0ire,

119

È possibile utilizzare il fork BS Typeahead che supporta le chiamate Ajax . Quindi sarai in grado di scrivere:

$('.typeahead').typeahead({
    source: function (typeahead, query) {
        return $.get('/typeahead', { query: query }, function (data) {
            return typeahead.process(data);
        });
    }
});

1
L '"ipotesi intelligente" di jQuery per il tipo di ritorno dei dati POST non funzionava quando sono tornato, ad esempio ["aardvark", "apple"]. Ho dovuto impostare esplicitamente il dataTypeparametro nella $.postchiamata. Vedi jQuery.post () .
Rusty Fausak,

1
@rfausak In alternativa, imposta l' Content-typeintestazione suapplication/json
Rusty Fausak il

23
sto ottenendo Uncaught TypeError: impossibile chiamare il metodo 'toLowerCase' di undefined
Krishnaprasad Varma

Nel link che hai inviato, non riesco nemmeno sourcea eseguire la funzione.
James,

8
Bella risposta! Vorrei invece utilizzare una richiesta GET, solo per soddisfare gli standard REST.
Mauro,

72

A partire da Bootstrap 2.1.0:

HTML:

<input type='text' class='ajax-typeahead' data-link='your-json-link' />

Javascript:

$('.ajax-typeahead').typeahead({
    source: function(query, process) {
        return $.ajax({
            url: $(this)[0].$element[0].dataset.link,
            type: 'get',
            data: {query: query},
            dataType: 'json',
            success: function(json) {
                return typeof json.options == 'undefined' ? false : process(json.options);
            }
        });
    }
});

Ora puoi creare un codice unificato, inserendo link "json-request" nel tuo codice HTML.


11
Ma lo cambierei per usarlo $(this)[0].$element.data('link').
Andrew Ellis,

oppurethis.$element.data('link')
Richard87,

51

Tutte le risposte si riferiscono al typeahead BootStrap 2, che non è più presente in BootStrap 3.

Per chiunque sia diretto qui alla ricerca di un esempio AJAX usando il nuovo Twitter post-Bootstrap typeahead.js , ecco un esempio funzionante. La sintassi è leggermente diversa:

$('#mytextquery').typeahead({
  hint: true,
  highlight: true,
  minLength: 1
},
{
  limit: 12,
  async: true,
  source: function (query, processSync, processAsync) {
    processSync(['This suggestion appears immediately', 'This one too']);
    return $.ajax({
      url: "/ajax/myfilter.php", 
      type: 'GET',
      data: {query: query},
      dataType: 'json',
      success: function (json) {
        // in this example, json is simply an array of strings
        return processAsync(json);
      }
    });
  }
});

In questo esempio vengono utilizzati sia i suggerimenti sincroni (la chiamata a processSync ) che i suggerimenti asincroni, quindi vedrai apparire immediatamente alcune opzioni, quindi ne verranno aggiunte altre. Puoi semplicemente usare l'uno o l'altro.

Ci sono molti eventi associabili e alcune opzioni molto potenti, incluso lavorare con oggetti piuttosto che stringhe, nel qual caso useresti la tua funzione di visualizzazione personalizzata per rendere i tuoi oggetti come testo.


1
Grazie. Un'altra domanda: con processAsync sto ottenendo "TypeError: tips.slice non è una funzione". Che aspetto avrebbe bisogno anche il JSON restituito? Ecco la mia ipotesi migliore: {: Suggerimenti => ["Cosa 1", "Cosa 2", "Cosa 3"]}
user1515295

1
Assicurarsi di restituire una stringa JSON valida. La tua funzione di suggerimento AJAX dovrebbe restituire una matrice di stringhe, ad esempio ["Thing 1","Thing 2"], o con una funzione di visualizzazione personalizzata, una matrice di oggetti in base alle tue esigenze, ad esempio[{"id":1,"label":"Foo"},{"id":2,"label":"Bar"}]
Jonathan Lidbeck,

Torno [{"id":1,"label":"Foo"},{"id":2,"label":"Bar"}], ora voglio mostrare due colonne nel menu a discesa typeahead con id ed etichetta. Come lo posso fare?
Vishal,

2
MIO DIO!!! Stavo cercando da 3 giorni nessuno di cui nessuno ne ha parlato. Fino ad ora stavo testando con la funzione di sincronizzazione. GRAZIE DUDE !!
Gilson PJ,

Grazie ! Funziona alla grande con bootstrap 4.3 e jquery 3.4. Tuttavia, le opzioni elencate non vengono evidenziate quando il mouse passa sopra di esso. Ho pensato che avrebbe dovuto far parte dello stesso typeahead.
Binita Bharati,

25

Ho aumentato il plug-in Bootstrap originale typeahead con funzionalità ajax. Molto facile da usare:

$("#ajax-typeahead").typeahead({
     ajax: "/path/to/source"
});

Ecco il repository github: Ajax-Typeahead


Ho guardato il codice di Gudbergur; francamente, questo mi è piaciuto di più. È un po 'più amichevole e offre più funzionalità. Ottimo lavoro Paolo! L'unica cosa che suggerirei è che nel tuo README ricordi all'utente che deve analizzare i suoi dati JSON in JS affinché il tuo codice sia in grado di usarlo correttamente. Avevo pensato che lo stessi analizzando per me, così mi ha appeso un po '. Altrimenti, carino, grazie! :)
Bane,

3
Il server restituisce una stringa anziché un oggetto JSON. $ .ajax () di jQuery viene utilizzato per effettuare la chiamata e si occupa dell'analisi.
Paul Warelis,

1
assolutamente corretto, grazie per la cattura! :) Questo plugin funziona molto bene.
Bane,

Ciao, come dovrebbe essere il lato server JSON? Sto ottenendo Uncaught TypeError: Cannot read property 'length' of undefined . Sto usando json_encode($array)e inviando le intestazioni giuste ( 'Content-Type: application/json; charset=utf-8'). versione jqueryjQuery v1.9.1
Kyslik il

5

Ho apportato alcune modifiche al jquery-ui.min.js:

//Line 319 ORIG:
this.menu=d("<ul></ul>").addClass("ui-autocomplete").appendTo(d(...
// NEW:
this.menu=d("<ul></ul>").addClass("ui-autocomplete").addClass("typeahead").addClass("dropdown-menu").appendTo(d(...

// Line 328 ORIG:
this.element.addClass("ui-menu ui-widget ui-widget-content ui-corner-all").attr...
// NEW:this.element.attr....

// Line 329 ORIG:
this.active=a.eq(0).children("a")
this.active.children("a")
// NEW:
this.active=a.eq(0).addClass("active").children("a")
this.active.removeClass("active").children("a")`

e aggiungi i seguenti css

.dropdown-menu {
    max-width: 920px;
}
.ui-menu-item {
    cursor: pointer;        
}

Funziona perfettamente


quale versione di jquery stai usando?
emeraldjava,

Se ne hai bisogno per jQuery 1.7.1 e jQuery UI 1.8.16, ho creato un GIST basato sulla correzione precedente che mostra dove modificare il file dell'interfaccia utente jQuery. gist.github.com/1884819 - le righe sono commentate con // modificato
Richard Hollis il

Questa è una domanda / risposta piuttosto vecchia, ma voglio solo dire che è sempre una cattiva pratica cambiare il codice dei componenti di terze parti. Dovrai rivedere tutte le modifiche ogni volta che le aggiorni. In questo caso particolare, i widget jQuery possono essere ereditati, il che è un modo molto più sicuro di personalizzarli. Quindi, fondamentalmente, crea il tuo widget, eredita da quello principale (il completamento automatico in questo caso) e libera la tua immaginazione! :)
AlexCode

3

Sto usando questo metodo

$('.typeahead').typeahead({
    hint: true,
    highlight: true,
    minLength: 1
},
    {
    name: 'options',
    displayKey: 'value',
    source: function (query, process) {
        return $.get('/weather/searchCity/?q=%QUERY', { query: query }, function (data) {
            var matches = [];
            $.each(data, function(i, str) {
                matches.push({ value: str });
            });
            return process(matches);

        },'json');
    }
});

Sarebbe bello se potessi aggiungere qualche spiegazione alla tua risposta. Ad esempio, qual è la differenza tra la tua soluzione e le soluzioni presentate nelle risposte già esistenti?
suonare il clacson il

2

È possibile effettuare chiamate utilizzando Bootstrap. La versione corrente non presenta alcun problema di aggiornamento dell'origine Problemi di aggiornamento dell'origine dati typeahead di Bootstrap con risposta post , ovvero la fonte di bootstrap una volta aggiornata può essere nuovamente modificata.

Fare riferimento di seguito per un esempio:

jQuery('#help').typeahead({
    source : function(query, process) {
        jQuery.ajax({
            url : "urltobefetched",
            type : 'GET',
            data : {
                "query" : query
            },
            dataType : 'json',
            success : function(json) {
                process(json);
            }
        });
    },
    minLength : 1,
});

2

A coloro che cercano una versione per caffè della risposta accettata:

$(".typeahead").typeahead source: (query, process) ->
  $.get "/typeahead",
    query: query
  , (data) ->
    process data.options

2

Ho esaminato questo post e tutto non voleva funzionare correttamente e alla fine ho messo insieme i bit da alcune risposte, quindi ho una demo funzionante al 100% e lo incollerò qui come riferimento: incollalo in un file php e assicurati che le inclusioni siano in il posto giusto.

<?php if (isset($_GET['typeahead'])){
    die(json_encode(array('options' => array('like','spike','dike','ikelalcdass'))));
}
?>
<link href="bootstrap.css" rel="stylesheet">
<input type="text" class='typeahead'>
<script src="jquery-1.10.2.js"></script>
<script src="bootstrap.min.js"></script>
<script>
$('.typeahead').typeahead({
    source: function (query, process) {
        return $.get('index.php?typeahead', { query: query }, function (data) {
            return process(JSON.parse(data).options);
        });
    }
});
</script>

2

Prova questo se il tuo servizio non sta restituendo la giusta intestazione del tipo di contenuto application / json:

$('.typeahead').typeahead({
    source: function (query, process) {
        return $.get('/typeahead', { query: query }, function (data) {
            var json = JSON.parse(data); // string to json
            return process(json.options);
        });
    }
});

1

AGGIORNAMENTO: ho modificato il mio codice usando questo fork

anche invece di usare $ .each sono passato a $ .map come suggerito da Tomislav Markovski

$('#manufacturer').typeahead({
    source: function(typeahead, query){
        $.ajax({
            url: window.location.origin+"/bows/get_manufacturers.json",
            type: "POST",
            data: "",
            dataType: "JSON",
            async: false,
            success: function(results){
                var manufacturers = new Array;
                $.map(results.data.manufacturers, function(data, item){
                    var group;
                    group = {
                        manufacturer_id: data.Manufacturer.id,
                        manufacturer: data.Manufacturer.manufacturer
                    };
                    manufacturers.push(group);
                });
                typeahead.process(manufacturers);
            }
        });
    },
    property: 'name',
    items:11,
    onselect: function (obj) {

    }
});

Tuttavia, sto riscontrando alcuni problemi

Uncaught TypeError: impossibile chiamare il metodo 'toLowerCase' di undefined

come puoi vedere in un post più recente, sto cercando di capire qui

spero che questo aggiornamento ti sia di aiuto ...


Non correlato a OP: utilizzerei Array.mapinvece $.eache sostituirei il contenuto dell'intera successfunzione di callback convar manufacturers = results.data.manufacturers.map(function (item) { return { id: item.Manufacturer.id, manufacturer: item.Manufacturer.manufacturer } });
Tomislav Markovski,

grazie @ TomislavMarkovski Ho modificato il mio codice come suggerisci.
mmoscosa,

0

Non ho un esempio funzionante per te né ho una soluzione molto pulita, ma lascia che ti dica cosa ho trovato.

Se guardi il codice javascript per TypeAhead è simile al seguente:

items = $.grep(this.source, function (item) {
    if (that.matcher(item)) return item
  })

Questo codice utilizza il metodo "grep" jQuery per abbinare un elemento nella matrice di origine. Non ho visto nessun posto in cui potresti agganciare una chiamata AJAX, quindi non esiste una soluzione "pulita" a questo.

Tuttavia, un modo un po 'confuso che puoi fare è sfruttare il modo in cui il metodo grep funziona in jQuery. Il primo argomento di grep è l'array di origine e il secondo argomento è una funzione che viene utilizzata per abbinare l'array di origine (nota che Bootstrap chiama il "matcher" che hai fornito quando lo hai inizializzato). Quello che potresti fare è impostare l'origine su un array di un elemento fittizio e definire il matcher come una funzione con una chiamata AJAX al suo interno. In questo modo, eseguirà la chiamata AJAX solo una volta (poiché l'array di origine contiene solo un elemento).

Questa soluzione non è solo confusa, ma soffrirà di problemi di prestazioni in quanto il codice TypeAhead è progettato per effettuare una ricerca su ogni pressione dei tasti (le chiamate AJAX dovrebbero realmente avvenire solo ogni pochi tasti o dopo un certo periodo di inattività). Il mio consiglio è di provarlo, ma attenersi a una libreria di completamento automatico diversa o utilizzarla solo per situazioni non AJAX in caso di problemi.


0

quando si utilizza ajax, provare $.getJSON()invece a $.get()riscontrare problemi con la corretta visualizzazione dei risultati.

Nel mio caso ho ottenuto solo il primo carattere di ogni risultato quando l'ho usato $.get(), anche se ho usato il json_encode()lato server.


0

io uso $().one() per risolvere questo; Quando la pagina viene caricata, invio ajax al server e aspetto di farlo. Quindi passare il risultato alla funzione. $().one()è importante. Perché forzare typehead.js a collegarsi all'input una volta. scusa per la cattiva scrittura.

(($) => {
    
    var substringMatcher = function(strs) {
        return function findMatches(q, cb) {
          var matches, substringRegex;
          // an array that will be populated with substring matches
          matches = [];
      
          // regex used to determine if a string contains the substring `q`
          substrRegex = new RegExp(q, 'i');
      
          // iterate through the pool of strings and for any string that
          // contains the substring `q`, add it to the `matches` array
          $.each(strs, function(i, str) {
            if (substrRegex.test(str)) {
              matches.push(str);
            }
          });
          cb(matches);
        };
      };
      
      var states = [];
      $.ajax({
          url: 'https://baconipsum.com/api/?type=meat-and-filler',
          type: 'get'
      }).done(function(data) {
        $('.typeahead').one().typeahead({
            hint: true,
            highlight: true,
            minLength: 1
          },
          {
            name: 'states',
            source: substringMatcher(data)
          });
      })
      

})(jQuery);
.tt-query, /* UPDATE: newer versions use tt-input instead of tt-query */
.tt-hint {
    width: 396px;
    height: 30px;
    padding: 8px 12px;
    font-size: 24px;
    line-height: 30px;
    border: 2px solid #ccc;
    border-radius: 8px;
    outline: none;
}

.tt-query { /* UPDATE: newer versions use tt-input instead of tt-query */
    box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075);
}

.tt-hint {
    color: #999;
}

.tt-menu { /* UPDATE: newer versions use tt-menu instead of tt-dropdown-menu */
    width: 422px;
    margin-top: 12px;
    padding: 8px 0;
    background-color: #fff;
    border: 1px solid #ccc;
    border: 1px solid rgba(0, 0, 0, 0.2);
    border-radius: 8px;
    box-shadow: 0 5px 10px rgba(0,0,0,.2);
}

.tt-suggestion {
    padding: 3px 20px;
    font-size: 18px;
    line-height: 24px;
    cursor: pointer;
}

.tt-suggestion:hover {
    color: #f0f0f0;
    background-color: #0097cf;
}

.tt-suggestion p {
    margin: 0;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<script src="https://twitter.github.io/typeahead.js/releases/latest/typeahead.bundle.js"></script>

<input class="typeahead" type="text" placeholder="where ?">


-1
 $('#runnerquery').typeahead({
        source: function (query, result) {
            $.ajax({
                url: "db.php",
                data: 'query=' + query,            
                dataType: "json",
                type: "POST",
                success: function (data) {
                    result($.map(data, function (item) {
                        return item;
                    }));
                }
            });
        },
        updater: function (item) {
        //selectedState = map[item].stateCode;

       // Here u can obtain the selected suggestion from the list


        alert(item);
            }

    }); 

 //Db.php file
<?php       
$keyword = strval($_POST['query']);
$search_param = "{$keyword}%";
$conn =new mysqli('localhost', 'root', '' , 'TableName');

$sql = $conn->prepare("SELECT * FROM TableName WHERE name LIKE ?");
$sql->bind_param("s",$search_param);            
$sql->execute();
$result = $sql->get_result();
if ($result->num_rows > 0) {
    while($row = $result->fetch_assoc()) {
    $Resut[] = $row["name"];
    }
    echo json_encode($Result);
}
$conn->close();

?>

Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.