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

简单介绍

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()

属性选项

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

名称 类型 默认值 描述
source array, function [ ] 提供查询的数据源,可以是一个字符串数组或者一个方法,该方法有两个参数:query 输入值和 process回调函数,回调函数可以在返回数据源的时候调用,以将数据处理成typeahead能识别的标准数据源。
items number 8 显示在下拉菜单中的列表数量的最大值
minLength number 1 触发autocomplete功能所需的最少输入字符个数
matcher function case insensitive 该方法用来确定一个query怎么匹配一个item,又一个入参item,表示与query匹配的实例,可以使用this.query来引用当前的query参数,如果query匹配成功则返回true。
sorter function exact match, case sensitive, case insensitive 该方法用于给数据源排序,有一个入参items,表示typeahead数据源实例,可以使用this.query来引用当前的query参数。
updater function returns selected item 该方法用于返回选择的搜索项,有一个入参item,表示typeahead数据源中返回的单个实例。
highlighter function highlights 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>

参考资料

版权声明:本文为博主原创文章,未经博主允许不得转载。

时间: 2024-08-08 09:41:33

Bootstrap typeahead使用问题记录及解决方案的相关文章

bootstrap Typeahead组件

使用 Bootstrap Typeahead 组件 Bootstrap 中的 Typeahead 组件就是通常所说的自动完成 AutoComplete,功能很强大,但是,使用上并不太方便.这里我们将介绍一下这个组件的使用. 第一,简单使用 首先,最简单的使用方式,就是直接在标记中声明,通过 data-provide="typeahead" 来声明这是一个 typeahead 组件,通过 data-source= 来提供数据.当然了,你还必须提供 bootstrap-typeahead.

使用sqoop1.4.4从oracle导入数据到hive中错误记录及解决方案

在使用命令导数据过程中,出现如下错误 sqoop import --hive-import --connect jdbc:oracle:thin:@192.168.29.16:1521/testdb --username NAME --passord PASS --verbose -m 1 --table T_USERINFO 错误1:File does not exist: hdfs://opt/sqoop-1.4.4/lib/commons-io-1.4.jar FileNotFoundEx

记:Android 服务站 问题记录与解决方案

1.dnsmasq域名劫持失败: 现象: 开启wifi热点后确实执行了dnsmasq命令,但是域名劫持失败. 原因: wifi热点开启命令执行后直接执行了dnsmasq命令,当热点开启过程时间很短时域名劫持可以成功:但是启动稍慢即会被系统启动的dnsmasq命令给杀掉并覆盖:所以会导致无效. 解决方案: 开启dnsmasq前定时检查wifi热点是否已经开启成功,成功后再kill掉系统启动的dnsmasq进程,再使用自定义的配置文件执行dnsmasq命令. 2.wifi热点启动频繁失败: 现象:

Bootstrap Typeahead自动补全

使用Bootstrap Typeahead 组件: Bootstrap 中的 Typeahead 组件就是通常所说的自动完成 AutoComplete,自动填充. 效果如图所示: 实现方式: 1.引入Bootstrap的相关 Js: <link href="${pageContext.request.contextPath}/static/bootstrap-3.3.4-dist/css/bootstrap.css" rel="stylesheet">&

数据库记录安全解决方案

数据库记录安全解决方案 http://netkiller.github.io/journal/mysql.security.html Mr. Neo Chen (netkiller), 陈景峰(BG7NYT) 中国广东省深圳市龙华新区民治街道溪山美地 518131 +86 13113668890 +86 755 29812080 <[email protected]> 版权 © 2014 http://netkiller.github.io 版权声明 转载请与作者联系,转载时请务必标明文章原始

typeahead.js 使用记录

github地址:https://github.com/twitter/typeahead.js 在aceAdmin界面模板中,有typeahead这一控件,版本号为0.10.2 , 这个版本对 minLength:0这个参数无效,所以我就到github中找到新版本0.11.1 替换,在此记录使用过程中的一些注意事项 基本代码 var gameNameList = ['abc', 'abd', 'cde', 'xyz']; var gameNameMatcher = function(strs)

移动端微信公众号开发中问题记录及解决方案

1. 关于字体大小.图片大小.块元素大小的确定,目前一种方法,使用rem,rem的计算方式 document.documentElement.style.fontSize = document.documentElement.clientWidth / 10.8 + 'px'; 其中10.8是设计图的大小除以100,这样就可以直接用设计图中的大小除以100的值. px, em, 和rem的区别: a. px是相对于显示器屏幕分辨率而言的. b. em是相对于对象内文本的字体尺寸,如果当前行内文本

使用git命令push到自己的仓库,显示Unknown且没有贡献记录的解决方案

一.问题的起因 今天用公司电脑在github上push时出现了以下问题: 用户名为unknown: 贡献记录为0: 二.解决方案 1,检查一遍自己的账号密码是否正确,如果正确,执行第二步骤操作: 2,,忽略SSL 问题解决了! 原文地址:https://www.cnblogs.com/OctoptusLian/p/9710638.html

错误记录及解决方案

Exception in thread "main" org.apache.ibatis.exceptions.PersistenceException: ### Error updating database.  Cause: java.sql.SQLException: Could not retrieve transation read-only status server### The error may involve zhao.ai.nan.dao.PersonDao.in