Twitter Bootstrap Typeahead Ajax Beispiel


280

Ich versuche, ein funktionierendes Beispiel für das typeahead- Element des Twitter-Bootstraps zu finden , das einen Ajax-Aufruf ausführt , um das Dropdown-Menü zu füllen.

Ich habe ein vorhandenes Beispiel für die automatische Vervollständigung von JQuerys, in dem die Ajax-URL für und die Verarbeitung der Antwort definiert sind

<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];
                }
            );
       ..

Was muss ich ändern, um dies in das Typeahead-Beispiel zu konvertieren?

<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];
                }
            );
       ..

Ich werde warten, bis das Problem " Unterstützung für Remotequellen für Typeahead hinzufügen " behoben ist.


Um genauer zu sein, frage ich mich, wie die Optionen für die automatische Vervollständigung und die Funktion zur Ergebnisverarbeitung den Textkopf-Optionen zugeordnet sind. Gibt es eine Reihe definierter Textalert-Ergebnisbehandlungsfunktionen, die überschrieben werden können, oder ist die benannte Methode von der zugrunde liegenden jquery-API geerbt.
Smaragdjava

1
Könnten Sie die Antwort von Stijn Van Bael jetzt als die richtige markieren? Die Antwort von bogert funktioniert nur für veraltete Versionen von Bootstrap.
Giles Roberts

Antworten:


302

Bearbeiten: typeahead ist in Bootstrap 3 nicht mehr enthalten. Check out:

Ab Bootstrap 2.1.0 bis 2.3.2 können Sie Folgendes tun:

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

So verwenden Sie JSON-Daten wie folgt:

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

Beachten Sie, dass die JSON-Daten vom richtigen MIME-Typ (application / json) sein müssen, damit jQuery sie als JSON erkennt.


3
Wie in der Typeahead-Verzweigung müssen Daten ein JSON-Array von Zeichenfolgen sein und der Inhaltstyp muss application / json sein.
Stijn Van Bael

9
Kann 2.1 JSON verwenden, das nicht nur ein String-Array ist? Ich muss also einen Wert für den Benutzer und eine ID verwenden, um die weitere Verarbeitung durchzuführen. Ist das möglich, ohne eine benutzerdefinierte Gabel aufzunehmen?
Anton

2
@Stijin Gibt es Beispiele dafür, wie diese anonyme Funktion hier verwendet wird, um eine ID für eine angezeigte Option zu verarbeiten? Vielen Dank!
Acyra

1
Ich möchte darauf hinweisen, dass die Verwendung dieser Methode dazu führt, dass für jeden Tastendruck auf der Eingabe ein AJAX namens aufgerufen wird . Wenn der Server im Wesentlichen statische Daten zurückgibt (dh nichts wirklich mit der Abfrage macht), kann dies ziemlich verschwenderisch sein.
Dologan

2
warum verwenden getstatt getJSON? Es scheint angemessener.
Greg0ire

119

Sie können die BS Typeahead-Gabel verwenden, die Ajax- Aufrufe unterstützt. Dann können Sie schreiben:

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

1
Die "intelligente Vermutung" von jQuery für den Rückgabetyp der POST-Daten funktionierte beispielsweise bei meiner Rückgabe nicht ["aardvark", "apple"]. Ich musste den dataTypeParameter im $.postAufruf explizit einstellen . Siehe jQuery.post () .
Rusty Fausak

1
@rfausak Alternativ können Sie den Content-typeHeader aufapplication/json
Rusty Fausak

23
Ich erhalte Uncaught TypeError: Die Methode 'toLowerCase' von undefined
Krishnaprasad Varma kann am

In dem Link, den Sie gesendet haben, wird die sourceFunktion nicht einmal ausgeführt.
James

8
Gute Antwort! Ich würde stattdessen eine GET-Anfrage verwenden, um die REST-Standards zu erfüllen.
Mauro

72

Ab 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);
            }
        });
    }
});

Jetzt können Sie einen einheitlichen Code erstellen und "json-request" -Links in Ihren HTML-Code einfügen.


11
Aber ich würde es ändern, um es zu benutzen $(this)[0].$element.data('link').
Andrew Ellis

oderthis.$element.data('link')
Richard87

51

Alle Antworten beziehen sich auf BootStrap 2 typeahead, das in BootStrap 3 nicht mehr vorhanden ist.

Für alle anderen, die hier Regie führen und nach einem AJAX-Beispiel mit dem neuen Post-Bootstrap- Twitter typeahead.js suchen , ist hier ein funktionierendes Beispiel. Die Syntax ist etwas anders:

$('#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 diesem Beispiel werden sowohl synchrone (der Aufruf von processSync ) als auch asynchrone Vorschläge verwendet, sodass einige Optionen sofort angezeigt werden und andere hinzugefügt werden. Sie können einfach das eine oder andere verwenden.

Es gibt viele bindbare Ereignisse und einige sehr leistungsstarke Optionen, einschließlich der Arbeit mit Objekten anstelle von Zeichenfolgen. In diesem Fall würden Sie Ihre eigene benutzerdefinierte Anzeigefunktion verwenden, um Ihre Elemente als Text zu rendern.


1
Danke dir. Noch eine Frage: Mit processAsync erhalte ich "TypeError: Vorschläge.Slice ist keine Funktion." Wie würde der zurückgegebene JSON auch aussehen müssen? Hier ist meine beste Vermutung: {: Vorschläge => ["Sache 1", "Sache 2", "Sache 3"]}
user1515295

1
Stellen Sie sicher, dass Sie eine gültige JSON-Zeichenfolge zurückgeben. Ihre AJAX-Vorschlagsfunktion sollte ein Array von Zeichenfolgen zurückgeben, z. B. ["Thing 1","Thing 2"]oder mit einer benutzerdefinierten Anzeigefunktion ein Array von Objekten gemäß Ihren Anforderungen, z. B.[{"id":1,"label":"Foo"},{"id":2,"label":"Bar"}]
Jonathan Lidbeck,

Ich [{"id":1,"label":"Foo"},{"id":2,"label":"Bar"}]kehre zurück . Jetzt möchte ich zwei Spalten in der Dropdown-Liste typeahead mit id und label anzeigen. Wie kann ich das machen?
Vishal

2
MEIN GOTT!!! Ich habe in den letzten 3 Tagen gesucht, niemand hat darüber gesprochen. Ich habe bis jetzt mit der Synchronisierungsfunktion getestet. DANKE DUDE !!
Gilson PJ

Vielen Dank ! Funktioniert hervorragend mit Bootstrap 4.3 und JQuery 3.4. Die aufgelisteten Optionen werden jedoch nicht hervorgehoben, wenn Sie mit der Maus darüber fahren. Ich dachte, es sollte Teil von typeahead selbst sein.
Binita Bharati

25

Ich habe das ursprüngliche typeahead Bootstrap-Plugin mit Ajax-Funktionen erweitert. Sehr einfach zu bedienen:

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

Hier ist das Github-Repo: Ajax-Typeahead


Ich habe mir Gudbergurs Code angesehen. Ehrlich gesagt hat mir das am besten gefallen. Es ist etwas freundlicher und bietet mehr Funktionalität. Gute Arbeit Paul! Ich würde nur vorschlagen, in Ihrer README-Datei den Benutzer daran zu erinnern, dass er seine JSON-Daten in JS analysieren muss, damit Ihr Code sie korrekt verwenden kann. Ich hatte angenommen, Sie haben es für mich analysiert, so dass ich ein bisschen aufgelegt habe. Ansonsten ganz nett, danke! :)
Bane

3
Ihr Server gibt eine Zeichenfolge anstelle eines JSON-Objekts zurück. $ .ajax () von jQuery wird zum Aufrufen verwendet und kümmert sich um das Parsen.
Paul Warelis

1
absolut richtig, danke für den Fang! :) Dieses Plugin funktioniert sehr gut.
Bane

Hallo, wie soll die Serverseite JSONaussehen? Ich bekomme Uncaught TypeError: Cannot read property 'length' of undefined . Ich verwende json_encode($array)und sende rechte Header ( 'Content-Type: application/json; charset=utf-8'). jquery versionjQuery v1.9.1
Kyslik

5

Ich habe einige Änderungen an der jquery-ui.min.js vorgenommen:

//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")`

und füge folgendes CSS hinzu

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

Funktioniert perfekt.


Welche Version von jquery ui min verwenden Sie?
Smaragdjava

Wenn Sie dies für jQuery 1.7.1 und jQuery UI 1.8.16 benötigen, habe ich basierend auf dem obigen Fix eine GIST erstellt, die zeigt, wo die jQuery UI-Datei geändert werden muss. gist.github.com/1884819 - Zeilen werden kommentiert mit // geändert
Richard Hollis

Dies ist eine ziemlich alte Frage / Antwort, aber ich möchte nur sagen, dass es immer eine schlechte Praxis ist, den Komponentencode von Drittanbietern zu ändern. Sie müssen alle Änderungen bei jedem Upgrade erneut überprüfen. In diesem speziellen Fall können jQuery-Widgets vererbt werden, was eine viel sicherere Möglichkeit ist, sie anzupassen. Erstellen Sie also im Grunde Ihr eigenes Widget, erben Sie das Kern-Widget (in diesem Fall die automatische Vervollständigung) und lassen Sie Ihrer Fantasie freien Lauf! :)
AlexCode

3

Ich benutze diese Methode

$('.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');
    }
});

Es wäre schön, wenn Sie Ihrer Antwort eine Erklärung hinzufügen könnten. Was ist beispielsweise der Unterschied Ihrer Lösung zu den Lösungen, die in den bereits vorhandenen Antworten dargestellt sind?
hupen

2

Mit Bootstrap kann man telefonieren. Die aktuelle Version weist keine Probleme mit der Quellaktualisierung auf. Probleme beim Aktualisieren der typeahead-Datenquelle von Bootstrap mit Post-Response , dh die Quelle des einmal aktualisierten Bootstraps kann erneut geändert werden.

Ein Beispiel finden Sie weiter unten:

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

Für diejenigen, die nach einer Coffeescript-Version der akzeptierten Antwort suchen:

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

2

Ich habe diesen Beitrag durchgesehen und alles wollte nicht richtig funktionieren und habe schließlich die Bits aus ein paar Antworten zusammengesetzt, sodass ich eine 100% funktionierende Demo habe und sie hier als Referenz einfügen werde - füge sie in eine PHP-Datei ein und stelle sicher, dass sie enthalten sind der richtige Ort.

<?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

Versuchen Sie dies, wenn Ihr Dienst nicht den richtigen Header für den Anwendungs- / JSON-Inhaltstyp zurückgibt:

$('.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

UPDATE: Ich änderte meinen Code mit dieser Gabel

Anstatt $ .each zu verwenden, habe ich auch zu $ ​​.map gewechselt, wie von Tomislav Markovski vorgeschlagen

$('#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) {

    }
});

Ich stoße jedoch auf einige Probleme, wenn ich bekomme

Nicht gefangener TypeError: Die Methode 'toLowerCase' von undefined kann nicht aufgerufen werden

Wie Sie in einem neueren Beitrag sehen können, versuche ich hier herauszufinden

Ich hoffe, dieses Update hilft Ihnen weiter ...


Unabhängig von OP: Ich würde Array.mapstattdessen verwenden $.eachund den Inhalt Ihrer gesamten successRückruffunktion durchvar manufacturers = results.data.manufacturers.map(function (item) { return { id: item.Manufacturer.id, manufacturer: item.Manufacturer.manufacturer } });
Tomislav Markovski

danke @TomislavMarkovski Ich habe meinen Code geändert, wie Sie vorschlagen.
mmoscosa

0

Ich habe weder ein funktionierendes Beispiel für Sie noch eine sehr saubere Lösung, aber lassen Sie mich Ihnen sagen, was ich gefunden habe.

Wenn Sie sich den Javascript-Code für TypeAhead ansehen, sieht er folgendermaßen aus:

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

Dieser Code verwendet die jQuery-Methode "grep", um ein Element im Quellarray abzugleichen. Ich habe keine Orte gesehen, an denen Sie einen AJAX-Anruf einbinden könnten, daher gibt es dafür keine "saubere" Lösung.

Eine etwas hackige Möglichkeit, dies zu tun, besteht darin, die Funktionsweise der grep-Methode in jQuery zu nutzen. Das erste Argument für grep ist das Quellarray, und das zweite Argument ist eine Funktion, die zum Abgleichen des Quellarrays verwendet wird (beachten Sie, dass Bootstrap den "Matcher" aufruft, den Sie bei der Initialisierung angegeben haben). Sie können die Quelle auf ein Dummy-Array mit einem Element setzen und den Matcher als Funktion mit einem AJAX-Aufruf definieren. Auf diese Weise wird der AJAX-Aufruf nur einmal ausgeführt (da Ihr Quellarray nur ein Element enthält).

Diese Lösung ist nicht nur hackig, sondern leidet auch unter Leistungsproblemen, da der TypeAhead-Code so konzipiert ist, dass er bei jedem Tastendruck nachschlägt (AJAX-Aufrufe sollten eigentlich nur alle paar Tastenanschläge oder nach einer bestimmten Leerlaufzeit erfolgen). Mein Rat ist, es zu versuchen, aber entweder bei einer anderen Autocomplete-Bibliothek zu bleiben oder diese nur für Nicht-AJAX-Situationen zu verwenden, wenn Sie auf Probleme stoßen.


0

Versuchen Sie bei der Verwendung von Ajax, $.getJSON()anstatt $.get()Probleme mit der korrekten Anzeige der Ergebnisse zu haben.

In meinem Fall habe ich bei meiner Verwendung nur das erste Zeichen jedes Ergebnisses erhalten $.get(), obwohl ich json_encode()serverseitig verwendet habe .


0

Ich benutze, $().one() um dies zu lösen. Wenn die Seite geladen ist, sende ich Ajax an den Server und warte, bis es fertig ist. Übergeben Sie dann das Ergebnis an die Funktion. $().one()ist wichtig. Weil typehead.js gezwungen wird, einmal an die Eingabe anzuhängen. Entschuldigung für das schlechte Schreiben.

(($) => {
    
    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();

?>

Durch die Nutzung unserer Website bestätigen Sie, dass Sie unsere Cookie-Richtlinie und Datenschutzrichtlinie gelesen und verstanden haben.
Licensed under cc by-sa 3.0 with attribution required.