twitter bootstrap typeahead ajax示例


280

我正在尝试查找twitter bootstrap typeahead元素的工作示例,该示例将进行ajax调用以填充其下拉列表。

我有一个现有的工作jQuery自动完成示例,该示例定义了ajax URL以及如何处理回复

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

我需要进行什么更改才能将其转换为预输入示例?

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

我将等待解决“ 为预输入添加远程源支持 ”问题得到解决。


更具体地说,我想知道自动完成选项和结果处理功能如何映射到textahead选项?是否有一组可以覆盖的已定义textalert结果处理函数,或者是从底层jquery api继承的命名方法。
emeraldjava

1
您现在可以将Stijn Van Bael的答案标记为正确的答案吗?bogert的答案仅适用于过时的Bootstrap版本。
吉尔斯·罗伯茨

Answers:


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。
Stijn Van Bael 2012年

9
2.1可以使用不只是字符串数组的json吗?我需要为用户提供一个值,并使用ID进行进一步处理。是否可以不使用自定义分叉?
安东

2
@Stijin是否有任何示例说明如何在此处使用该匿名函数来处理所显示选项的ID?谢谢!
Acyra

1
我想指出的是,使用此方法会导致对输入中的每个击键进行一次 AJAX调用。如果服务器返回的是本质上是静态的数据(即对查询实际上没有做任何事情),那么这可能会很浪费。
Dologan

2
为什么用get代替getJSON?似乎更合适。
greg0ire

119

您可以使用支持ajax调用的BS Typeahead分支。然后,您将能够编写:

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

1
@rfausak或者,将Content-type标头设置为application/json
Rusty Fausak 2012年

23
我收到未捕获的TypeError:无法调用未定义的方法“ toLowerCase”
Krishnaprasad Varma 2012年

在您发送的链接中,我什source至没有使函数执行。
詹姆斯

8
好答案!我会改用GET请求,只是为了满足REST标准。
毛罗(Mauro)2012年

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')
Andrew Ellis

this.$element.data('link')
Richard87 '16

51

所有响应均涉及BootStrap 2提前输入,而BootStrap 3中不再存在。

对于其他在这里使用新的Bootstrap Twitter typeahead.js查找AJAX示例的人来说,这是一个有效的示例。语法略有不同:

$('#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:proposal.slice不是函数”。返回的JSON需要什么样子?这是我最好的猜测:{:suggestions => [“ Thing 1”,“ Thing 2”,“ Thing 3”]}}
user1515295 2015年

1
确保您返回有效的JSON字符串。您的AJAX建议函数应返回一个字符串数组,例如["Thing 1","Thing 2"],或者使用自定义显示函数,根据您的需要返回一个对象数组,例如[{"id":1,"label":"Foo"},{"id":2,"label":"Bar"}]
Jonathan Lidbeck,2015年

我返回[{"id":1,"label":"Foo"},{"id":2,"label":"Bar"}],现在我想在typeahead下拉列表中显示带有id和label的两列。我怎样才能做到这一点?
维沙尔

2
天哪!!!我从过去的三天开始一直没有人提及此事。到目前为止,我一直在测试同步功能。多谢,伙计!!
Gilson PJ

谢谢 !与bootstrap 4.3和jquery 3.4配合使用时效果很好。但是,当鼠标悬停在列出的选项上时,它们不会突出显示。我认为它应该是预先输入的一部分。
Binita Bharati

25

我使用ajax功能增强了原始的typeahead Bootstrap插件。非常容易使用:

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

这是github仓库:Ajax-Typeahead


我看过古德伯格的代码;坦白说,我最喜欢这一个。它更加友好,并提供更多功能。保罗,干得好!我只建议您在自述文件中提醒用户,他们需要将JSON数据解析为JS,以便您的代码能够正确使用它。我以为您正在为我解析它,所以让我挂了一下。否则,很好,谢谢!:)
贝恩(Bane)2012年

3
您的服务器返回一个字符串而不是一个JSON对象。jQuery的$ .ajax()用于进行调用,它负责解析。
保罗·沃里斯

1
绝对正确,谢谢您的帮助!:)这个插件很好用。
贝恩

您好,服务器端应如何显示JSON?我越来越Uncaught TypeError: Cannot read property 'length' of undefined 。我正在使用json_encode($array)并发送正确的标题('Content-Type: application/json; charset=utf-8')。jQuery版本jQuery 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;        
}

完美的作品。


您正在使用哪个版本的ui ui min?
emeraldjava

如果您需要jQuery 1.7.1和jQuery UI 1.8.16,则我已根据上述修复程序创建了一个GIST,该指南显示了更改jQuery UI文件的位置。gist.github.com/1884819-注释行//已修改
Richard Hollis

这是一个很老的问题/答案,但是我只想说更改第三方组件代码始终是一个坏习惯。每次升级时,您都必须重新访问所有更改。在这种特殊情况下,可以继承jQuery小部件,这是自定义它们的更安全的方法。因此,基本上,创建您自己的窗口小部件,从核心窗口小部件(在这种情况下为自动完成)继承并释放您的想象力!:)
AlexCode 2014年

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

如果您可以在回答中添加一些解释,那就太好了。例如,与现有答案中提供的解决方案相比,您的解决方案有什么区别?
2014年

2

可以使用Bootstrap拨打电话。当前版本没有任何源更新问题 难以通过后期响应来更新Bootstrap的typeahead数据源,即,一旦更新,引导源就可以再次修改。

请参考以下示例:

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

如果您的服务没有返回正确的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

更新:我使用 fork 修改了我的代码

也没有使用$ .each,而是按照Tomislav Markovski的建议更改为$ .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) {

    }
});

但是我遇到了一些问题

未捕获的TypeError:无法调用未定义的方法“ toLowerCase”

正如您在较新的帖子中看到的那样,我正在尝试找出此处

希望此更新对您有帮助...


无关OP:我会用Array.map,而不是$.each和更换你的整个的内容success与回调函数var manufacturers = results.data.manufacturers.map(function (item) { return { id: item.Manufacturer.id, manufacturer: item.Manufacturer.manufacturer } });
托米斯拉夫Markovski

谢谢@TomislavMarkovski我按照您的建议修改了我的代码。
mmoscosa 2012年

0

我没有适合您的示例,也没有非常干净的解决方案,但是请允许我告诉您所找到的内容。

如果您查看TypeAhead的javascript代码,则如下所示:

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

此代码使用jQuery“ grep”方法来匹配源数组中的元素。我没有看到可以挂接到AJAX调用的任何地方,因此没有针对此的“干净”解决方案。

但是,一种可行的方法是利用grep方法在jQuery中的工作方式。grep的第一个参数是源数组,第二个参数是用于匹配源数组的函数(注意,Bootstrap会在初始化时调用您提供的“ matcher”)。您可以做的是将源设置为虚拟的一元数组,然后将匹配器定义为带有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();

?>

By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.