【问题标题】:Use different value from JSON data instead of displayKey using Typeahead使用来自 JSON 数据的不同值,而不是使用 Typeahead 的 displayKey
【发布时间】:2014-03-20 15:23:55
【问题描述】:

我已经开始使用 Typeahead.js,并且正在努力找出一种方法,允许用户输入和搜索公司名称,一旦选择输入相关的公司代码。

.json 文件:

[{
    "company_name": "Facebook",
    "code": "fb",
}, {
    "company_name": "Google",
    "code": "goog",
}, {
    "company_name": "Yahoo",
    "code": "yhoo",
}, {
    "company_name": "Apple",
    "code": "aapl",
}, {
    "company_name": "Royal Mail",
    "code": "rmg.l",
}]

.js 脚本:

var stocks = new Bloodhound({
    datumTokenizer: function(d) {
        return Bloodhound.tokenizers.whitespace(d.code);
    },
    queryTokenizer: Bloodhound.tokenizers.whitespace,
    limit: 3,
    prefetch: {
        url: 'javascripts/stockCodes.json',
        filter: function(list) {
            return $.map(list, function(stock) {
                return {
                    code: stock
                };
            });
        }
    }
});

stocks.initialize();

$('.typeahead').typeahead(null, {
    name: 'stocks',
    displayKey: 'code',
    source: stocks.ttAdapter()
});

目前,这仅在用户在输入字段中键入时显示代码列表。但是,我想知道是否有办法让他们搜索code,但一旦选择,文本框中的值是company_name?这甚至可以使用这个插件。任何帮助将不胜感激。

谢谢!

【问题讨论】:

  • 你能改变你的数据结构吗?
  • @Tomanow 是的,当然。我只是认为这种结构会很有效。谢谢
  • 我刚刚更新了我的答案。现在应该更准确了。

标签: javascript jquery json typeahead.js


【解决方案1】:

displayKey 用于指示用户选择条目后应在下拉列表中显示哪个键在输入字段中。

如果您希望下拉列表中显示的条目与输入字段中的条目不同,您需要使用自定义模板。

来自documentation

suggestion – 用于呈现单个建议。如果设置,这必须是 预编译模板。关联的建议对象将作为 语境。默认为包裹在 p 标签中的 displayKey 的值,即 <p>{{value}}</p>.

这样的事情应该可以工作:

$('.typeahead').typeahead(null, {
    name: 'stocks',
    displayKey: 'company_name',
    source: stocks.ttAdapter(),
    templates: {
        suggestion: function (stock) {
            return '<p>' + stock.code + '</p>';
        }
    }
});

提交的模板将用于在下拉列表中显示stock.code,而stock.company_name将在用户选择条目后显示在输入字段中。

【讨论】:

    【解决方案2】:

    我不是 jQuery / JavaScript-Guru。所以我更喜欢简单的方法。只是为了了解我稍后查看我的代码时做了什么......

    感谢Eric Saupe我找到了一个聪明的解决方案:

    //JSON FILE
    [
        {
            "company_name": "Facebook",
            "code": "fb",
        },
        {
            "company_name": "Google",
            "code": "goog",
        },
        {
            "company_name": "Yahoo",
            "code": "yhoo",
        },
        {
            "company_name": "Apple",
            "code": "aapl",
        },
        {
            "company_name": "Royal Mail",
            "code": "rmg.l",
        },
     ]
    

    // JS 脚本

       var stocks = new Bloodhound({
            datumTokenizer: Bloodhound.tokenizers.obj.whitespace('company_name'),
            queryTokenizer: Bloodhound.tokenizers.whitespace,
            remote: 'javascripts/stockCodes.json'
        });
    
        stocks.initialize();
    
        $('.typeahead').typeahead(
            null, {
            name: 'stocks',
            displayKey: 'company_name',
            source: stocks.ttAdapter()
        }).on('typeahead:selected', function(event, data){            
            $('.typeahead').val(data.code);        
        });
    

    只需使用docs on github 中描述的预输入自定义事件。

    希望,这会有所帮助(当它仅供我自己以后参考时)。

    JSFIDDLE

    【讨论】:

    • 您还想处理 'typeahead:autocompleted'。
    • 似乎是最好的解决方案,但 JSFIDDLE 不再起作用了。点击的时候是写公司全名。
    • typeahead:selected 还是typeahead:select?官方文档说后者。无论哪种方式,我都无法触发该事件。我在您的小提琴中添加了alert(data.code);,但它也没有触发。正确的方法应该是什么?
    • JSFIDDLE 按预期工作。我用 Firefox 和 Chrome 进行了测试。我不知道它是 :selected 还是 :select。它对我有用 :selected 同时我切换到 jQuery Typeahead (runningcoder.org/jquerytypeahead/documentation)。它有据可查且功能丰富,配置更简单(恕我直言)。
    • 即使在使用setTimeout 方法如:setTimeout(function() { $('.typeahead').val(data.code); }, 1); 之后,离开输入框时仍将值改回。所以,我不得不转向@Esseb 的基于模板的解决方案。
    【解决方案3】:

    您需要使用“displayKey”变量。请参阅下面的 typeahead 文档中的复制粘贴:

    displayKey – 对于给定的建议对象,确定它的字符串表示形式。这将在选择建议后设置输入控件的值时使用。可以是键字符串或将建议对象转换为字符串的函数。默认为value

    https://github.com/twitter/typeahead.js/blob/master/doc/jquery_typeahead.md

    您的具体代码将是这样的:

    var stocks = new Bloodhound({
            datumTokenizer: function(d) { return Bloodhound.tokenizers.whitespace(d.code); },
            queryTokenizer: Bloodhound.tokenizers.whitespace,
            limit: 3,
            prefetch: {
                url: 'javascripts/stockCodes.json',
                filter: function(list) {
                    // This should not be required, but I have left it incase you still need some sort of filtering on your server response
                    return $.map(list, function(stock) { return { code: stock.code, company_name: stock.company_name }; });
                }
            }
        });
    
        stocks.initialize();
    
        $('.typeahead').typeahead(null, {
            name: 'stocks',
            displayKey: function(stock) {
               return stock.company_name;
            },
            source: stocks.ttAdapter()
        });
    

    我在自己的网站上也有非常相似的要求,而且我的工作没有问题。虽然我没有尝试过这个特定的例子,所以如果它有效,请告诉我。

    记得致电stocks.clearPrefetchCache(); 清除缓存以便更轻松地跟踪错误。

    【讨论】:

      【解决方案4】:

      如果我没看错,我相信这就是你想要的:

      var stocksData = [{
          "Facebook": "fb",
      }, {
          "Google": "goog",
      }, {
          "Yahoo": "yhoo",
      }, {
          "Apple": "aapl",
      }, {
          "Royal Mail": "rmg.l",
      }, ];
      
      var stocks = new Bloodhound({
          datumTokenizer: function (d) {
                        for (var prop in d) {
                            return Bloodhound.tokenizers.whitespace(d[prop]);
                        }
      
          },
          queryTokenizer: Bloodhound.tokenizers.whitespace,
          limit: 3,
          local: stocksData,
      });
      
      stocks.initialize();
      
      $('input').typeahead(null, {
          name: 'stocks',
          displayKey: function(stocks) {
              for (var prop in stocks) {
                  return prop;    
              }
          },
          source: stocks.ttAdapter()
      });
      

      您当然希望将本地更改为预取/远程,就像您对 json 文件所做的那样。

      更新

      FIDDLE

      【讨论】:

      • 感谢您的回答,非常感谢。我刚刚开始使用上面小提琴中提供的代码。我不确定我是否正确解释了问题,但我试图弄清楚如何将关联值放置在输入文本框中,而不是键值。例如,键入“Facebook”应在下拉列表中显示 Facebook,但是一旦选择,文本框值将显示“fb”而不是“Facebook”。我已经尝试调整提供的代码,但还没有设法合并此功能。感谢您对此的帮助。
      【解决方案5】:

      遇到了同样的问题,无法使用 display 或 displayKey 属性。通过将 name 属性添加到源对象来解决它:

                  $.each(stocks, function (i, item) {
                      item.name = item.company_name;
                  });
      

      【讨论】:

        【解决方案6】:

        display参数中添加需要显示的值:

        $(".comp-search").typeahead({
            hint: true,
            highlight: true,
            minLength: 1,
            displayKey: 'company_name',
        }, {
            source: engine.ttAdapter(),
            templates: {
                empty: ['<div class="list-group search-results-dropdown"><div class="list-group-item">Nothing found.</div></div>'],
                header: ['<div class="list-group search-results-dropdown">'],
                suggestion: function (data) {
                    return '<a href="javascript:void(0);" class="list-group-item">' + data.company_name + '</a>';
                }
            },
            display: function(data) { return data.company_name; }
        });
        

        希望对你有帮助

        【讨论】:

          猜你喜欢
          • 2015-10-16
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 2020-09-27
          相关资源
          最近更新 更多