приклад twitter bootstrap typeahead ajax


280

Я намагаюся знайти робочий приклад елемента twitter bootstrap typeahead, який зробить дзвінок ajax, щоб заповнити його спадне меню.

У мене є існуючий приклад автозаповнення jquery, який визначає URL-адресу ajax і як обробляти відповідь

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

Що мені потрібно змінити, щоб перетворити це на приклад 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];
                }
            );
       ..

Я буду чекати, коли проблема " Додати підтримку віддалених джерел для typeahead " буде вирішена.


Щоб бути більш конкретним, мені цікаво, як параметри автозаповнення та обробки результатів відображають параметри текстових завдань? Чи є набір визначених функцій обробки результатів textalert, які можна переосмислити, або метод, названий успадкованим від базового api jquery.
emeraldjava

1
Чи можете ви позначити відповідь Штійна Ван Баеля як правильну зараз? Відповідь bogert працює лише для застарілих версій Bootstrap.
Giles Roberts

Відповіді:


302

Редагувати: typeahead більше не входить у Bootstrap 3. Перевірте:

З Bootstrap 2.1.0 до 2.3.2 ви можете це зробити:

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

Для споживання таких даних JSON:

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

Зауважте, що дані JSON повинні мати правильний тип mime (application / json), тому jQuery розпізнає їх як JSON.


3
Як і у вилці Typeahead, дані мають бути масивом рядків JSON, а тип вмісту повинен бути application / json.
Штійн Ван Баель

9
може 2.1 використовувати json, який не є просто рядковим масивом? мені потрібно так значення для користувача та використовувати ідентифікатор для подальшої обробки. Це можливо без підбору спеціальної вилки?
Антон

2
@Stijin Чи є приклади того, як ця анонімна функція буде використана тут для обробки ідентифікатора для відображеної опції? Дякую!
Acyra

1
Я хотів би зазначити, що використання цього методу призводить до того, що AJAX називається для кожного натискання клавіші на вході. Якщо сервер повертає фактично статичні дані (тобто насправді нічого не робить із запитом), це може бути досить марно.
Дологан

2
навіщо використовувати getзамість getJSON? Це здається більш доречним.
greg0ire

119

Ви можете використовувати виделку BS Typeahead, яка підтримує дзвінки ajax. Тоді ви зможете написати:

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

1
«Розумна думка» Jquery для повертається типу даних POST не працювала , коли я повернувся, наприклад, ["aardvark", "apple"]. Мені довелося чітко встановити dataTypeпараметр у $.postвиклику. Див. JQuery.post () .
Rusty Fausak

1
@rfausak Як варіант, встановіть Content-typeзаголовок наapplication/json
Rusty Fausak

23
я отримую Uncaught TypeError: Не можу викликати метод 'toLowerCase' невизначеного
Krishnaprasad Varma

У посиланні, яке ви надіслали, я навіть не отримую sourceфункції для виконання.
Джеймс

8
Гарна відповідь! Я б використав запит GET, щоб просто відповідати стандартам REST.
Мауро

72

Починаючи з 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);
            }
        });
    }
});

Тепер ви можете зробити уніфікований код, розмістивши у своєму HTML-коді посилання "json-request".


11
Але я би змінив це на використання $(this)[0].$element.data('link').
Ендрю Елліс

абоthis.$element.data('link')
Richard87

51

Усі відповіді стосуються BootStrap 2 typehahead, якого більше немає в BootStrap 3.

Для всіх, хто скеровує сюди, шукаючи приклад AJAX, використовуючи новий Twitter-файл після завантаження typeahead.js , ось робочий приклад. Синтаксис трохи інший:

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

У цьому прикладі використовуються як синхронні (виклик processSync ), так і асинхронні пропозиції, тому ви побачите, що деякі параметри з’являються негайно, а потім додаються інші. Можна просто використовувати те чи інше.

Існує безліч погодних подій і кілька дуже потужних варіантів, включаючи роботу з об'єктами, а не рядками. У такому випадку ви використовуєте власну функцію відображення для відображення елементів як текст.


1
Дякую. Ще одне питання: з ProcessAsync я отримую "TypeError: offers.slice - це не функція." Як би надто виглядав повернений JSON? Ось моя найкраща здогадка: {: offers => ["Thing 1", "Thing 2", "Thing 3"]}
користувач1515295

1
Переконайтеся, що ви повернули дійсний рядок JSON. Ваша функція пропозиції AJAX повинна повертати масив рядків, наприклад ["Thing 1","Thing 2"], або за допомогою спеціальної функції відображення, масив об'єктів відповідно до ваших потреб, наприклад[{"id":1,"label":"Foo"},{"id":2,"label":"Bar"}]
Джонатан Лідбек

Я повертаюся [{"id":1,"label":"Foo"},{"id":2,"label":"Bar"}], зараз я хочу показати дві колонки в друкованому випадаючому меню з ідентифікатором і влучним. Як я можу це зробити?
Вішал

2
БОЖЕ!!! Я шукав останні 3 дні, про це ніхто не згадував. Я досі тестував функцію синхронізації. ДЯКУЮ, ЧУВАК!!
Gilson PJ

Дякую ! Чудово підходить для завантажувальної програми 4.3 та jquery 3.4. Але перераховані параметри не виділяються, коли миша наводить на неї курсор. Я подумав, що це повинно бути частиною самої друкарні.
Бініта Бхараті

25

Я доповнив оригінальний плагін Bootstrap typeahead з можливостями ajax. Дуже простий у використанні:

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

Ось github repo: Ajax-Typeahead


Я подивився код Гудбергура; відверто кажучи, мені це найбільше сподобалось. Це трохи привітніше і пропонує більше функціоналу. Гарна робота Пол! Єдине, що я б запропонував, це у тому, щоб README нагадував користувачеві, що їм потрібно проаналізувати свої JSON-дані в JS, щоб ваш код міг правильно їх використовувати. Я припускав, що ти розбираєш це для мене, щоб трохи повісити мене. Інакше досить приємно, дякую! :)
Бейн

3
Ваш сервер повертає рядок замість об'єкта JSON. $ .ajax () jQuery використовується для здійснення дзвінка, і він дбає про розбір.
Пол Вареліс

1
абсолютно правильно, дякую за улов! :) Цей плагін працює дуже добре.
Бейн

Привіт, як має JSONвиглядати сторона сервера ? Я отримую Uncaught TypeError: Cannot read property 'length' of undefined . Я використовую json_encode($array)та надсилаю правильні заголовки ( 'Content-Type: application/json; charset=utf-8'). версія jqueryjQuery v1.9.1
Kyslik

5

Я зробив деякі зміни на 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")`

і додайте наступний css

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

Працює ідеально.


яку версію jquery ui min ви використовуєте?
смарагдовава

Якщо вам це потрібно для jQuery 1.7.1 та jQuery UI 1.8.16, тоді я створив ГІСТ на основі наведеного вище виправлення, яке показує, де потрібно змінити файл інтерфейсу jQuery. gist.github.com/1884819 - рядки коментуються // модифіковано
Річард Холліс

Це досить старе питання / відповідь, але я просто хочу сказати, що завжди погана практика змінити код компонентів сторонніх виробників. Вам доведеться переглянути всі зміни щоразу, коли ви їх оновлюєте. У цьому конкретному випадку віджети jQuery можуть бути успадковані, що є набагато безпечнішим способом їх налаштування. Отже, створіть власний віджет, успадкуйте від основного (автозаповнення в даному випадку) та розкрийте свою фантазію! :)
AlexCode

3

Я використовую цей метод

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

Було б добре, якби ви могли додати трохи пояснень до своєї відповіді. Наприклад, у чому різниця вашого рішення порівняно з рішеннями, представленими у вже існуючих відповідях?
ганч

2

Можна телефонувати за допомогою Bootstrap. Поточна версія не має жодних проблем з оновленням джерела. Проблеми з оновленням джерела даних типу Bootstrap з надісланою відповіддю , тобто джерело завантажувальної програми після оновлення можна знову змінити.

Нижче див. Приклад:

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

Тим, хто шукає кофескрипт прийнятої відповіді:

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

2

Я пройшов цю посаду, і все не хотіло правильно працювати, і в кінцевому підсумку розібрав біти разом з кількох відповідей, тому у мене є 100% робоча демонстрація і вставити її сюди для довідки - вставте це у файл php і переконайтеся, що включено в правильне місце.

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

Спробуйте це, якщо ваша служба не повертає потрібний заголовок типу вмісту програми / 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

ОНОВЛЕННЯ: Я змінив свій код за допомогою цієї виделки

також замість $ .each я змінив $ .map як запропонував Томіслав Марковський

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

    }
});

Однак я стикаюся з деякими проблемами, отримуючи

Uncaught TypeError: Неможливо викликати метод 'toLowerCase' невизначеного

як ви бачите на новій посаді, я намагаюся розібратися тут

сподіваюся, що це оновлення допоможе вам ...


Не має відношення до ОП: Я б Array.mapзамість цього використовував $.eachі замінював зміст всієї вашої successфункції зворотного викликуvar manufacturers = results.data.manufacturers.map(function (item) { return { id: item.Manufacturer.id, manufacturer: item.Manufacturer.manufacturer } });
Томіслав Марковський,

дякую @TomislavMarkovski Я змінив код, як ви пропонуєте.
mmoscosa

0

У мене немає робочого прикладу для вас, і я не маю дуже чистого рішення, але дозвольте розповісти, що я знайшов.

Якщо ви подивитеся на код javascript для TypeAhead, він виглядає приблизно так:

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

Цей код використовує метод "grep" jQuery для відповідності елементу в вихідному масиві. Я не бачив місць, де ви могли підключитися під час виклику AJAX, тому для цього немає "чистого" рішення.

Однак, один дещо химерний спосіб зробити це - скористатися тим, як працює метод grep в jQuery. Перший аргумент grep - це вихідний масив, а другий аргумент - це функція, яка використовується для узгодження вихідного масиву (повідомлення Bootstrap називає "відповідник", який ви надали при ініціалізації). Що ви можете зробити, це встановити джерело на макетний одноелементний масив і визначити матчер як функцію з викликом AJAX в ньому. Таким чином, він запустить виклик AJAX лише один раз (оскільки у вашому вихідному масиві є лише один елемент).

Це рішення не тільки хакітне, але воно буде страждати від проблем продуктивності, оскільки код TypeAhead призначений для пошуку під час кожного натискання клавіші (дзвінки AJAX дійсно повинні відбуватися лише кожні кілька натискань клавіш або після певного часу простою). Моя порада - спробувати, але дотримуйтесь будь-якої іншої бібліотеки автозаповнення або використовуйте це лише для ситуацій, що не належать до AJAX, якщо у вас виникли проблеми.


0

під час використання ajax спробуйте $.getJSON()замість того, $.get()якщо у вас виникли проблеми з правильним відображенням результатів.

У моєму випадку я отримав лише перший символ кожного результату, коли використовував $.get(), хоча я використовував json_encode()серверну сторону.


0

я використовую $().one() для вирішення цього питання; Коли сторінка завантажується, я надсилаю ajax на сервер і чекаю, коли буде зроблено. Потім переведіть результат у функціонування. $().one()важливо. Тому що змусити typehead.js приєднатися до введення один раз. вибачте за неправильне написання.

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

?>

Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.