Bootstrap typeahead如何返回名称和ID?

8

嗨!我正在使用 Twitter Bootstrap 的 typeahead:

我调用一个返回 json_encode 响应的页面, 该页面返回名称和 ID,

我希望 typeahead 列表会显示名称列表, 当我选择其中一个名称时, 将 id 值写入一个隐藏字段。

调用工作正常,并且编写字段应该很容易。 我不知道如何区分名称和 ID。

现在,在搜索时,在建议列表中,我可以看到如下返回结果:

名字1:ID1 名字2:ID2

我只想看到名称但仍保留 ID 值。

我该怎么做?

 $(function(){
    $("#typeahead_<? print $key; ?>").typeahead(
        {
        source: function(query, process)
                    {
                    $.ajax({
                        url:    '/getAjaxProducts',
                        type:   'POST',
                        data:   'query=' + query,
                        dataType: 'JSON',
                        async: true,
                        success: function(data)
                                {
                                process(data);
                                }
                            });                 
                    }
        });
});
6个回答

21

一个包含名称/ID对的典型JSON文档看起来像这样:

[
  {
    "id": 1
    "name": "firstName"
  },
  {
    "id": 2
    "name": "secondName"
  }
]

在这里的策略是,在解析结果时构建一个对象字面量,将名称映射到ID,同时仅使用名称填充typeahead:

var productNames = new Array();
var productIds = new Object();
$.getJSON( '/getAjaxProducts', null,
        function ( jsonData )
        {
            $.each( jsonData, function ( index, product )
            {
                productNames.push( product.name );
                productIds[product.name] = product.id;
            } );
            $( '#product' ).typeahead( { source:productNames } );
        } );

用户从自动完成列表中选择一项后,您可以使用以下方式引用所选项目:

$( '#product' ).val()

你可以通过以下代码获取所选项目的ID:

productIds[$( '#product' ).val()]
从你的问题来看,JSON文档的结构可能有些不同,所以你需要根据实际情况更改解析方式,但是相同的一般策略仍然适用。

19
这个解决方案意味着名称是唯一的。在大多数情况下,它们可能是唯一的,但我觉得有必要指出这一点。 - RickardN
使用最新的typeahead.js,它是local:productNames而不是source:productNames。 - Dunc
2
我无法想象在名称不唯一的情况下使用场景会是什么。这意味着您将在下拉列表中拥有两个完全相同的选项,而用户无法区分它们。用户该如何知道选择哪一个呢? - Corby Page
2
使用案例是当您有人的姓名时,例如John James和Bill Johnson。您可以通过呈现带有个人资料图片的自定义模板来为用户区分(因此,您的JSON可能需要具有id、名称和个人资料图片URL字段)。 - bratsche
这个解决方案一次性加载了所有数据,对吧?因为我没有看到“query”参数。如果后端只返回了一定数量的数据,那么就会出现问题。例如,你需要为更具体的数据分配查询参数。 - Jason Liu

11

抱歉“复活”这篇帖子,但我快要疯了!

如果你们中的一些人在使用这些示例代码时遇到问题(所有代码都未能正常工作,而是返回“未定义”的值而不是显示名称),只需添加

displayKey: 'name',

将“name”替换为来自您的远程源返回的标签变量名称

(这很难找到最新的样例,在网上找到的大多数样例都是针对以前版本的typeahead,不兼容新版本...)


这是正确的方法。任何依赖于显示字符串的解决方案都很容易出现问题。 - Cesar

9
......updater: function (item) {
        var item = JSON.parse(item);
        console.log(item.name); 
        $('#VehicleAssignedTechId').val(item.id);       
        return item.name;
    }

在 typeahead 的 updater 中,您可以放置如上代码,这允许您将所选值添加到文本框中或者在其他隐藏字段中添加其值。

完整的 ajax 调用如下:

$('#VehicleAssignedTechName').typeahead({
    source: function(query, process) {
        var $url =SITE_URL+ 'api/vehicle_techfield_typeahead/' + query + '.json';
        var $items = new Array;
        $items = [""];
        $.ajax({
            url: $url,
            dataType: "json",
            type: "POST",
            success: function(data) {
                console.log(data);
                $.map(data, function(data){
                    var group;
                    group = {
                        id: data.id,
                        name: data.name,                            
                        toString: function () {
                            return JSON.stringify(this);
                            //return this.app;
                        },
                        toLowerCase: function () {
                            return this.name.toLowerCase();
                        },
                        indexOf: function (string) {
                            return String.prototype.indexOf.apply(this.name, arguments);
                        },
                        replace: function (string) {
                            var value = '';
                            value +=  this.name;
                            if(typeof(this.level) != 'undefined') {
                                value += ' <span class="pull-right muted">';
                                value += this.level;
                                value += '</span>';
                            }
                            return String.prototype.replace.apply('<div style="padding: 10px; font-size: 1.5em;">' + value + '</div>', arguments);
                        }
                    };
                    $items.push(group);
                });

                process($items);
            }
        });
    },
    property: 'name',
    items: 10,
    minLength: 2,
    updater: function (item) {
        var item = JSON.parse(item);
        console.log(item.name); 
        $('#VehicleAssignedTechId').val(item.id);       
        return item.name;
    }
});

很有用,谢谢。只需要添加substr方法。substr: function(string) { return String.prototype.substr.apply(this.name, arguments); } - Alex Z

1
我的解决方案是:

var productNames = new Array();
var productIds = new Object();
$.getJSON( '/getAjaxProducts', null,
        function ( jsonData )
        {
            $.each( jsonData, function ( index, product )
            {
                productNames.push( product.id + product.name );
                productIds[product.id + product.name] = product.id;
            } );
            $( '#product' ).typeahead( { source:productNames } );
        } );

在我的情况下,product.id是一个代码,因此在typeahead控件中显示它是有用的。这样可以避免重复名称的风险。

0

当我尝试处理用户名和ID时,我遇到了同样的问题。一开始我采用了一个棘手的修复方案,但后来我用适当的解决方案解决了它。

看一下这个吧,

$('#search').typeahead({
 source: function(query, process) {
 var $url = "/controller/function/list_users/?q="+query;
 var $datas = new Array;
 $datas = [""];
 $.ajax({
 url: $url,
 dataType: "json",
 type: "GET",
 success: function(data) {
 $.map(data, function(data){
 var group;
 group = {
 id: data.id,
 name: data.user_name,
 toString: function () {
 return JSON.stringify(this);
 //return this.variable;
 },
 toLowerCase: function () {
 return this.name.toLowerCase();
 },
 indexOf: function (string) {
 return String.prototype.indexOf.apply(this.name, arguments);
 },
 replace: function (string) {
 var value = '';
 value += this.name;
 if(typeof(this.name) != 'undefined') {
 value += ' <span class="pull-right muted">';
 //value += this.name;
 value += '</span>';
 }
 return String.prototype.replace.apply('<div style="padding: 10px; font-size: 1em;">' + value + '</div>', arguments);
 }
 };
 $datas.push(group);
 });
process($datas);
 }
 });
 },
 property: 'user_name',
 items: 10,
 minLength: 2,
 updater: function (item) {
 var item = JSON.parse(item);
 $('#hiddenId').val(item.id);
 $('#username').val(item.name);
//you can perform your actions here
//example</p>
//location = '/controller/function/'+item.id+'/edit';
 //document.redirect = location;
}
});

也请查看这个链接。

http://vaisakhvm.wordpress.com/2013/07/31/twitter-bootstrap-typeahead-process-multiple-values/


0
我注意到使用这段代码时,如果匹配包含字母“st”,则自动完成建议中会包括样式标签。
例如,建议的匹配将显示:

style="padding: 10px; font-size: 1.5em;">standard

而不是

standard

我将替换函数更改为:
replace: function (string) {
  return String.prototype.replace.apply(this.name, arguments);
}

显然,您会失去额外的格式,但它不会在“st”匹配上中断(我认为它也会在“di”或其他div标记的子字符串上中断)。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接