twitter bootstrap typeahead ajax example

280

Próbuję znaleźć działający przykład twitterowego elementu typu bootstrap , który wykona wywołanie ajax w celu zapełnienia menu rozwijanego.

Mam istniejący działający przykład autouzupełniania jquery, który definiuje adres URL ajax do i sposób przetwarzania odpowiedzi

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

Co muszę zmienić, aby przekonwertować to na przykład?

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

Zaczekam na rozwiązanie problemu „ Dodaj obsługę źródeł zdalnych dla typeahead ”.

szmaragdowa
źródło
Mówiąc ściślej zastanawiam się, w jaki sposób opcje autouzupełniania i funkcja obsługi wyników mapują się na opcje textahead? Czy istnieje zestaw zdefiniowanych funkcji obsługi wyników textalert, które można zastąpić, czy też metoda jest dziedziczona z bazowego interfejsu API jquery.
emeraldjava,
1
Czy mógłbyś teraz oznaczyć odpowiedź Stijn Van Bael jako prawidłową? Odpowiedź Bogerta działa tylko w przypadku nieaktualnych wersji Bootstrap.
Giles Roberts,

Odpowiedzi:

302

Edycja: typeahead nie jest już dołączany do Bootstrap 3. Sprawdź:

Począwszy od wersji Bootstrap 2.1.0 do 2.3.2, możesz to zrobić:

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

Aby wykorzystać dane JSON w następujący sposób:

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

Zauważ, że dane JSON muszą być odpowiedniego typu MIME (application / json), więc jQuery rozpoznaje je jako JSON.

Stijn Van Bael
źródło
3
Podobnie jak w rozwidleniu Typeahead, dane muszą być tablicą ciągów JSON, a typem treści musi być application / json.
Stijn Van Bael
9
czy 2.1 może używać json, który nie jest tylko tablicą łańcuchów? Muszę więc podać wartość dla użytkownika i użyć identyfikatora do dalszego przetwarzania. Czy to możliwe bez podnoszenia niestandardowego widelca?
Anton
2
@Stijin Czy istnieją przykłady wykorzystania tej anonimowej funkcji w celu przetworzenia identyfikatora wyświetlanej opcji? Dzięki!
Acyra
1
Chciałbym zauważyć, że użycie tej metody powoduje wywołanie AJAX dla każdego naciśnięcia klawisza na wejściu. Jeśli serwer zwraca zasadniczo dane statyczne (tzn. Nie robi nic z zapytaniem), może to być dość marnotrawstwem.
Dologan
2
dlaczego warto korzystać getzamiast getJSON? Wydaje się bardziej odpowiednie.
greg0ire
119

Możesz użyć widelca BS Typeahead, który obsługuje wywołania ajax. Następnie będziesz mógł napisać:

$('.typeahead').typeahead({
    source: function (typeahead, query) {
        return $.get('/typeahead', { query: query }, function (data) {
            return typeahead.process(data);
        });
    }
});
bogert
źródło
1
„Inteligentne zgadywanie” jQuery dla typu zwracanego danych POST nie działało, na przykład, gdy zwracałem ["aardvark", "apple"]. Musiałem wyraźnie ustawić dataTypeparametr w $.postwywołaniu. Zobacz jQuery.post () .
Rusty Fausak
1
@rfausak Ewentualnie ustaw Content-typenagłówek naapplication/json
Rusty Fausak
23
Otrzymuję Uncaught TypeError: Nie można wywołać metody „toLowerCase” niezdefiniowanej
Krishnaprasad Varma
W przesłanym linku nie dostaję nawet sourcefunkcji do wykonania.
James
8
Niezła odpowiedź! Zamiast tego użyłbym żądania GET, aby spełnić standardy REST.
Mauro,
72

Począwszy od 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);
            }
        });
    }
});

Teraz możesz utworzyć zunifikowany kod, umieszczając linki „żądanie json” w kodzie HTML.

Thantifaxath
źródło
11
Ale zmieniłbym to na użycie $(this)[0].$element.data('link').
Andrew Ellis
lubthis.$element.data('link')
Richard87,
51

Wszystkie odpowiedzi odnoszą się do typu BootStrap 2, który nie jest już obecny w BootStrap 3.

Dla każdego, kogo tu skierowano, szukającego przykładu AJAX za pomocą nowego postahead.js po uruchomieniu Bootstrap , oto działający przykład. Składnia jest nieco inna:

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

W tym przykładzie użyto zarówno sugestii synchronicznej (wywołanie processSync ), jak i asynchronicznej, więc niektóre opcje pojawią się natychmiast, a inne zostaną dodane. Możesz po prostu użyć jednego lub drugiego.

Istnieje wiele możliwych do powiązania zdarzeń i kilka bardzo potężnych opcji, w tym praca z obiektami zamiast ciągami, w którym to przypadku użyłbyś własnej funkcji wyświetlania do renderowania swoich elementów jako tekstu.

Jonathan Lidbeck
źródło
1
Dziękuję Ci. Jeszcze jedno pytanie: dzięki processAsync otrzymuję komunikat „Typ Błąd: sugestie.slice nie jest funkcją”. Jak też powinien wyglądać zwrócony JSON? Oto moje najlepsze przypuszczenie: {: sugestie => [„Rzecz 1”, „Rzecz 2”, „Rzecz 3”]}
user1515295
1
Upewnij się, że zwrócisz prawidłowy ciąg JSON. Twoja funkcja sugestii AJAX powinna zwrócić tablicę ciągów, np. ["Thing 1","Thing 2"]Lub z niestandardową funkcją wyświetlania, tablicę obiektów według twoich potrzeb, np.[{"id":1,"label":"Foo"},{"id":2,"label":"Bar"}]
Jonathan Lidbeck
Wracam [{"id":1,"label":"Foo"},{"id":2,"label":"Bar"}], teraz chcę pokazać dwie kolumny w rozwijanym menu z id i etykietą. Jak mogę to zrobić?
Vishal
2
MÓJ BOŻE!!! Szukałem z ostatnich 3 dni, nikt o tym nie wspominał. Do tej pory testowałem z funkcją synchronizacji. DZIĘKI STARY!!
Gilson PJ
Dzięki ! Działa świetnie z bootstrap 4.3 i jquery 3.4. Jednak wymienione opcje nie są podświetlane, gdy wskaźnik myszy najedzie nad nią. Myślałem, że to powinno być częścią samego typu.
Binita Bharati,
25

Rozszerzyłem oryginalną wtyczkę TypeAhead Bootstrap o funkcje ajax. Bardzo łatwy w użyciu:

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

Oto repozytorium github: Ajax-Typeahead

Paul Warelis
źródło
Spojrzałem na kod Gudbergura; szczerze mówiąc, najbardziej mi się podobało. Jest nieco bardziej przyjazny i oferuje więcej funkcji. Dobra robota Paul! Jedyne, co zasugerowałbym, to w README przypomnieć użytkownikowi, że musi on parsować swoje dane JSON na JS, aby kod mógł poprawnie z niego korzystać. Zakładałem, że analizujesz to dla mnie, więc to mnie rozłączyło. W przeciwnym razie całkiem miło, dziękuję! :)
Bane
3
Twój serwer zwraca ciąg zamiast obiektu JSON. Do wywołania służy jQuery $ .ajax (), który zajmuje się parsowaniem.
Paul Warelis
1
absolutnie poprawne, dziękuję za haczyk! :) Ta wtyczka działa bardzo dobrze.
Zmora
Cześć, jak powinna JSONwyglądać strona serwera ? Dostaję Uncaught TypeError: Cannot read property 'length' of undefined . Używam json_encode($array)i wysyłam odpowiednie nagłówki ( 'Content-Type: application/json; charset=utf-8'). wersja jqueryjQuery v1.9.1
Kyslik
5

Wprowadziłem kilka zmian w pliku 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")`

i dodaj następujące css

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

Działa idealnie.

bmoers
źródło
jakiej wersji jquery ui min używasz?
emeraldjava
Jeśli potrzebujesz tego w przypadku jQuery 1.7.1 i jQuery UI 1.8.16, utworzyłem GIST na podstawie powyższej poprawki, która pokazuje, gdzie zmienić plik interfejsu użytkownika jQuery. gist.github.com/1884819 - linie są komentowane // zmodyfikowane
Richard Hollis
To dość stare pytanie / odpowiedź, ale chcę tylko powiedzieć, że zmiana kodu komponentów innych firm zawsze jest złą praktyką. Będziesz musiał ponownie przejrzeć wszystkie zmiany za każdym razem, gdy je uaktualnisz. W tym konkretnym przypadku widżety jQuery mogą być dziedziczone, co jest znacznie bezpieczniejszym sposobem ich dostosowania. Zasadniczo stwórz własny widżet, odziedzicz po głównym (w tym przypadku autouzupełnianie) i uwolnij swoją wyobraźnię! :)
AlexCode
3

Używam tej metody

$('.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');
    }
});
Krava
źródło
Byłoby miło, gdybyś mógł dodać wyjaśnienie do swojej odpowiedzi. Na przykład, jaka jest różnica między Twoim rozwiązaniem a rozwiązaniami przedstawionymi w już istniejących odpowiedziach?
honk
2

Można nawiązywać połączenia za pomocą Bootstrap. W bieżącej wersji nie występują problemy z aktualizacją źródła. Problemy z aktualizacją typowego źródła danych Bootstrap z odpowiedzią post , tzn. Źródło aktualizacji po aktualizacji można ponownie zmodyfikować.

Przykład znajduje się poniżej:

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,
});
neoeahit
źródło
2

Do osób poszukujących coffeescriptowej wersji zaakceptowanej odpowiedzi:

$(".typeahead").typeahead source: (query, process) ->
  $.get "/typeahead",
    query: query
  , (data) ->
    process data.options
Hendrik
źródło
2

Przejrzałem ten post i wszystko nie chciałem działać poprawnie i ostatecznie poskładałem bity razem z kilku odpowiedzi, więc mam w 100% działające demo i wkleję go tutaj w celach informacyjnych - wklej to do pliku php i upewnij się, że dołączone są w dobre miejsce.

<?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>
l0ft13
źródło
2

Wypróbuj to, jeśli twoja usługa nie zwraca odpowiedniego nagłówka typu treści aplikacji / 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);
        });
    }
});
Andres
źródło
1

AKTUALIZACJA: Zmodyfikowałem swój kod za pomocą tego widelca

także zamiast używania $ .each zmieniłem na $ .map, jak zasugerował 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) {

    }
});

Dostaję jednak pewne problemy

Uncaught TypeError: Nie można wywołać metody „toLowerCase” niezdefiniowanej

jak widać w nowym poście, staram się tutaj znaleźć

mam nadzieję, że ta aktualizacja pomoże ci ...

mmoscosa
źródło
Niepowiązany z OP: Array.mapZamiast tego użyłbym $.eachi zastąpiłbym treść całej successfunkcji wywołania zwrotnegovar manufacturers = results.data.manufacturers.map(function (item) { return { id: item.Manufacturer.id, manufacturer: item.Manufacturer.manufacturer } });
Tomislav Markovski
dziękuję @TomislavMarkovski Zmodyfikowałem kod, jak sugerujesz.
mmoscosa
0

Nie mam dla ciebie działającego przykładu ani nie mam bardzo czystego rozwiązania, ale powiem ci, co znalazłem.

Jeśli spojrzysz na kod JavaScript dla TypeAhead, wygląda to tak:

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

Ten kod używa metody „grep” jQuery w celu dopasowania elementu w tablicy źródłowej. Nie widziałem żadnych miejsc, w których można by nawiązać połączenie AJAX, więc nie ma „czystego” rozwiązania tego problemu.

Jednak jednym z dość pospiesznych sposobów na zrobienie tego jest skorzystanie ze sposobu, w jaki metoda grep działa w jQuery. Pierwszym argumentem grep jest tablica źródłowa, a drugim argumentem jest funkcja używana do dopasowania tablicy źródłowej (zauważ, że Bootstrap wywołuje „dopasowujący”, który podałeś podczas inicjowania). To, co możesz zrobić, to ustawić źródło na sztuczną tablicę jednoelementową i zdefiniować moduł dopasowywania jako funkcję z wywołaniem AJAX. W ten sposób wywoła wywołanie AJAX tylko raz (ponieważ tablica źródłowa zawiera tylko jeden element).

To rozwiązanie jest nie tylko hackerskie, ale będzie miało problemy z wydajnością, ponieważ kod TypeAhead jest zaprojektowany do wyszukiwania za każdym naciśnięciem klawisza (wywołania AJAX powinny naprawdę występować tylko po kilku naciśnięciach klawiszy lub po pewnym czasie bezczynności). Radzę spróbować, ale trzymaj się innej biblioteki autouzupełniania lub używaj jej tylko w sytuacjach innych niż AJAX, jeśli napotkasz jakiekolwiek problemy.

Aamer Abbas
źródło
0

gdy używasz ajax, spróbuj $.getJSON()zamiast$.get() jeśli masz problemy z poprawnym wyświetlaniem wyników.

W moim przypadku dostałem tylko pierwszy znak każdego wyniku, gdy go użyłem $.get(), chociaż użyłem strony json_encode()serwera.

larsbo
źródło
0

używam $().one() do rozwiązania tego; Po załadowaniu strony wysyłam ajax do serwera i czekam na zakończenie. Następnie przekaż wynik do funkcji. $().one()jest ważne. Ponieważ wymusza jednokrotne dołączenie pliku typehead.js do danych wejściowych. przepraszam za złe pisanie.

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

Ali Karimi
źródło
-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();

?>

Mohamed Ayed
źródło