Bootstrap typeahead使用问题记录及解决方案

来源:互联网 发布:php中变量的作用域 编辑:程序博客网 时间:2024/05/19 19:13

简单介绍

Bootstrap typeahead插件是用来完成输入框的自动完成、模糊搜索和建议提示的功能,支持ajax数据加载,类似于jquery的流行插件Autocomplete。

typeahead的使用方式有两种:通过数据属性字段的方式和通过Javascript加载的方式。

1. 通过属性字段的方式

在输入文本框input组件里添加data-provide="typeahead"这个属性字段表示使用typeahead扩展插件:

<input type="text" data-provide="typeahead">

也可以通过设置autocomplete="off"来避免浏览器自己的自动完成功能,防止与插件使用相混。

2. 通过Javascript加载的方式

通过手动的在js中调用typeahead函数:

$('.typeahead').typeahead()

属性选项

具体数据相关的配置通过几个选项字段和函数控制,如下表所示:

名称类型默认值描述sourcearray, function[ ]提供查询的数据源,可以是一个字符串数组或者一个方法,该方法有两个参数:query 输入值和 process回调函数,回调函数可以在返回数据源的时候调用,以将数据处理成typeahead能识别的标准数据源。itemsnumber8显示在下拉菜单中的列表数量的最大值minLengthnumber1触发autocomplete功能所需的最少输入字符个数matcherfunctioncase insensitive该方法用来确定一个query怎么匹配一个item,又一个入参item,表示与query匹配的实例,可以使用this.query来引用当前的query参数,如果query匹配成功则返回true。sorterfunctionexact match, case sensitive, case insensitive该方法用于给数据源排序,有一个入参items,表示typeahead数据源实例,可以使用this.query来引用当前的query参数。updaterfunctionreturns selected item该方法用于返回选择的搜索项,有一个入参item,表示typeahead数据源中返回的单个实例。highlighterfunctionhighlights all default matches该方法用于高亮选取最终的选择项,又一个入参item,表示typeahead数据源中返回的单个实例,返回值是一个html。


​具体的使用实例可以自行Google或借鉴我最后列出的几个参考资料。

问题记录

这篇文章主要记录自己初次使用typeahead时遇到的难题,以及最终的解决方法,希望能给遇到类似问题的小伙伴们一个有用的参考。

首先,我的业务需求是输入一个话题topic,该话题的数据源是从后台数据库获取的,需要支持模糊搜索(至于左模糊、右模糊还是全模糊,就看查询数据库时的sql语句怎么写了),因此必须使用ajax异步加载的方式获取数据,于是写了下面这样一个ajax函数提供数据源:

source: function (query, process) {        return $.ajax({            url: '/showoff/watermark/fetchTopics',            type: 'post',            data: {topicName: query},            dataType: 'json',            success: function (result) {                        // 这里省略resultList的处理过程,处理后resultList是一个字符串列表,                // 经过process函数处理后成为能被typeahead支持的字符串数组,作为搜索的源                return process(resultList);                                                       }        });}

结果是可以行得通的,如下图所示:


2

但这里有个问题:
在提交表单时,我们后台需要传入的是话题的id,而不是搜索框里显示的话题name。这里通过typeahead获取的只有name,上面写的ajax函数里从后台传来的数据也只有name列表,该怎么办呢?

不难想到有下面两个解决方案:

  1. 在提交的时候直接把话题name传过去,然后在后台处理逻辑里再通过name搜索其对应的id。
  2. 将话题id和name绑定后一起传到页面,然后在话题输入框下面放置一个隐藏的话题id输入框。在搜索时只需要name作为数据源,在选取某个name后,将其对应的id值放到隐藏的id输入框里面。

方案1处理起来很简单,但同时也很low,而且可能因为页面多传了个空格什么的导致数据库搜索失败,容易出错。

方案2看起来挺不错的,可怎么实现呢?如何在选取某个搜索值后做其它的操作?source函数做不到这点。看一下上面选项表中的几个函数,其中有一个updater方法,该方法用来返回最终选取的某个值,顾名思义,我们也可以在方法返回之前做更新动作,比如设置某个输入框的值。但有几个问题:

  • topic id和name如何进行绑定?以对象的方式还是map的方式?
  • 在返回数据源时是只返回name列表用于搜索,还是返回name和id的组合列表?如果只返回name列表,那么在updater函数里是取不到与name对应的id值的;如果返回组合列表,那么搜索时显示的就不仅是name了。
  • 是不是可以在数据源里返回绑定的组合列表,然后自定义搜索匹配方式,item只显示name呢?

在参考资料的帮助下,我看了下typeahead js库里关于上面选项表里几个方法的默认实现,最终得到了解决方案:

  • 后台将topic id和topic name以对象列表的形式传过来,到了ajax里进行解析处理,得到一个id和name组合的json字符串数组,通过process函数处理后返回。
  • 重写matcher、sorter、highlighter和updater这四个方法,将原来里面的item实例全部变成item.name实例,表示要通过name进行搜索匹配、高亮和排序,而与id五官。
  • 最后,在updater方法里将topic id的隐藏输入框的值更新为item.id值即可。

按照上面的思路最终实现如下,这里贴上完整的typeahead相关的代码:

typeahead输入框:

<input type="text" id="topicInput" name="topicName" placeholder="请输入话题"     autocomplete="off" data-provide="typeahead" />

隐藏的topic id输入框:

<form:hidden id="topicId" name="topicId" path="labelId"/>

最终的typeahead实现js:

<script type="text/javascript">    $('#topicInput').typeahead({  source: function (query, process) {        return $.ajax({            url: '/showoff/watermark/fetchTopics',            type: 'post',            data: {topicName: query},            dataType: 'json',            success: function (result) {                     // 这里的数据解析根据后台传入格式的不同而不同                 if(result.code == "1") {                    var json = JSON.parse(result.data.data);                                    var resultList = json.topicList.map(function (item) {                        var aItem = { id: item.id, name: item.displayName };                        return JSON.stringify(aItem);                    });                                return process(resultList);                                              } else {                    alert(result.msg);               }              }        });    },     matcher: function (obj) {        var item = JSON.parse(obj);        return ~item.name.toLowerCase().indexOf(this.query.toLowerCase())    },    sorter: function (items) {                  var beginswith = [], caseSensitive = [], caseInsensitive = [], item;        while (aItem = items.shift()) {            var item = JSON.parse(aItem);            if (!item.name.toLowerCase().indexOf(this.query.toLowerCase()))                     beginswith.push(JSON.stringify(item));            else if (~item.name.indexOf(this.query)) caseSensitive.push(JSON.stringify(item));            else caseInsensitive.push(JSON.stringify(item));        }        return beginswith.concat(caseSensitive, caseInsensitive)    },    highlighter: function (obj) {        var item = JSON.parse(obj);        var query = this.query.replace(/[\-\[\]{}()*+?.,\\\^$|#\s]/g, '\\$&')        return item.name.replace(new RegExp('(' + query + ')', 'ig'), function ($1, match) {            return '<strong>' + match + '</strong>'        })    },    updater: function (obj) {        var item = JSON.parse(obj);        $('#topicId').attr('value', item.id);        return item.name;    } })</script>

参考资料

  • Javascript · Bootstrap
  • 使用 Bootstrap Typeahead 组件 - 冠军 - 博客园
  • Bootstrap typeahead ajax result format - Example [结果格式的例子引导Typeahead Ajax] - 问题-字节技术
  • typeahead Bloodhound完整例子
3 1
原创粉丝点击
热门问题 老师的惩罚 人脸识别 我在镇武司摸鱼那些年 重生之率土为王 我在大康的咸鱼生活 盘龙之生命进化 天生仙种 凡人之先天五行 春回大明朝 姑娘不必设防,我是瞎子 联壁金融资金冻结提现不出来怎么办 联壁金融提现不到帐怎么办 联壁金融提现迟迟不到帐怎么办 客户说平安福现金价值低怎么办 2个月宝宝肚脐凸出来怎么办 西安华润万家预付卡丢了怎么办 租房签了一年合同想走怎么办 京东寄包裹在速递易里面该怎么办 翼码科技辅助码被删掉了怎么办 用别人的身份证注册的手机号怎么办 大v线做到假线了怎么办 有个摄像头网段不同搜不到怎么办 百度网盘离线下载有违规内容怎么办 抖音上传的照片与音乐不同步怎么办 社保卡里面的钱用完了怎么办 医保卡里面的钱用完了怎么办 手机通知栏变成了搜索栏怎么办 小米手机账号密码忘了手机号怎么办 暑假工没签合同押工资了的怎么办 在日本雅虎拍卖网站买到假货怎么办 没有百度糯米账号但是买票了怎么办 拼多多商家版登陆密码忘记了怎么办 安卓下载的软件闪退怎么办 老司机影视院开通会员看不了怎么办 梦幻西游手游苹果手机打不开怎么办 拼多多笔订单被判定虚假发货怎么办 苹果手机微信接收不到信息怎么办 内衣穿32太小穿34空杯怎么办 楼下的把下水管道堵死了怎么办?? 微信绑定的手机号码已停机怎么办 绑定微信的手机号停机了怎么办验证 绑定手机停机微信怎么验证码怎么办 五菱之光雨刷开关手柄断了怎么办 快手家长控制模式密码忘了怎么办 有陌生人要求你拉他入群怎么办 手机一天接到多个陌生电话怎么办 阳光惠生活登录密码忘了怎么办 一个身份证注册了两个支付宝怎么办 买手办拆了发现坏了怎么办 六个月宝宝喝贝因美过敏怎么办 超市盘点少的货扣员工工资怎么办