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

2023-11-02

简单介绍

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>

参考资料

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

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

  • Jasmine-jQuery loadFixtures 未定义

    我对整个茉莉花的事情仍然很陌生 在过去的几个小时里我陷入了这个问题 我尝试使用 loadFixture 加载外部夹具文件 我使用 Jasmine 2 0 0 和 Jasmine jQuery 2 0 5 ReferenceError loa
  • html 表格单元格的条件格式

    是否有现成的解决方案可以对 HTML 表格进行条件格式设置 通过条件格式 我更感兴趣的是根据该列或其他列 在同一个表中 的值 数字 将不同的颜色作为单元格背景 类似于我们在 Excel 条件格式 gt 色阶 gt 红黄绿中的内容 我想在通过
  • GWT - 如何组织项目以拥有多个网页以及它们之间的导航

    我是 GET 的新手 顺便说一句 它给我留下了深刻的印象 并且发现它对于像我这样熟悉 C NET 桌面技术并愿意编写 Web 应用程序的人来说非常有吸引力 我根据 GWT Eclipse 向导生成的示例启动了自己的项目 该项目生成带有面板的
  • 了解 sort() 比较函数

    我正在使用一个电子商务平台 该平台无法重新排序产品属性字段的选项 这真的很糟糕 因为要插入新选项 您几乎必须删除所有现有选项并重新开始 我正在尝试在客户端进行操作 这是我正在处理的内容 这是针对鞋码的 9 EE 9 1 2 EE 10 EE
  • 在鼠标光标位置添加 cytoscape 节点

    我想在画布上的单击事件上的鼠标箭头位置添加一个 cytoscape 节点 我怎样才能做到这一点 我的方法 效果不太好 我可以通过单击创建一个节点 但无法确保创建的节点的位置位于我单击的位置 使用这样的东西 cy click function
  • 如何导入和导出 javascript ES6 类

    我是 javascript 和 nodejs 的新手 我正在使用这个项目来发展我的技能并学习新技术 目前我的项目使用多个相互依赖的类 类文件位于不同的目录中 我当前正在尝试使用 export 和 require 语句来允许在其他文件中引用类
  • 将文本大小调整为矩形 在 Canvas HTML5 中调整大小

    我是 Canvas 新手 我正在创建一个网站 以在调整矩形大小时增加文本 我尝试了很多 但没有任何效果 实际上 我希望如果我仅按其宽度调整矩形大小 向左拉伸 向右拉伸 则仅应增加文本宽度而不是字体大小 我已经完成了字体大小 但发现增加孤立文
  • 有没有办法将变量从 javascript 导入到 sass 或反之亦然?

    我正在制作一个依赖于块概念的 CSS 网格系统 所以我有一个基本文件 例如 max columns 4 block width 220px block height 150px block margin 10px 它被 mixin 使用 m
  • 判断一个数字是否能被 3 或 5 整除 (FizzBu​​zz)

    如何根据输出是否能被 3 或 5 整除来更改输出 如果它能被 3 整除 我想显示 rock 如果它能被 5 整除 我想显示 star 类似于 FizzBu zz 如果两者都有 他们都会看到 这是我的代码 if var n Math floo
  • 循环遍历元素并逐步为每个元素应用 CSS 规则

    我有一个网格布局 每个网格布局中都有不同数量的元素 我想动态添加内联grid column通过循环遍历 div 中存在的每个元素的 CSS 规则 ul 与一类 list 所以 HTML 代码的输出需要是 ul class list ul u
  • 在 Fabric.js 中按宽度/高度在另一个画布对象内居中和缩放画布对象

    Goal 将一个对象 水平和垂直 置于另一个对象 矩形或组 的中心canvas via Fabric js或者通过Javascript保持原始对象的长宽比相同 但也不超过父对象的宽度 高度比例 父对象 矩形或组 不会居中于canvas元素
  • 如何使用 vanilla JS 实现可维护的反应式 UI

    今天我遇到了一个问题 可以通过使用像 Vue 这样的反应式和状态管理框架来轻松解决 遗憾的是 无法使用它 以下 简化 情况 链接到代码笔 https codepen io theiaz pen BazErKV 我们有一个服务器渲染的页面 其
  • 获取点击的的DOM路径

    HTML div class lol a class rightArrow href a div 伪代码 rightArrow click function rightArrowParents this dom dom is the pse
  • 禁用特定 div 上的 Tab 键

    我有以下结构 div div Some content div div Some content div div 我想 禁用 div2 上的 tab 键 我的意思是按下 tab 键时 div2 的元素不会获得焦点 有没有简单的方法可以使用
  • Ember Data 中出现“超出最大调用堆栈大小”错误的原因可能是什么?

    Ember 发布新版本 3 6 0 后 我开始在控制台中收到错误 rsvp js 24 未捕获 RangeError 超出最大调用堆栈大小 在 WeakMap get 在 getCacheFor metal js 25 在 Computed
  • Firebase 警告:使用 Firebase Cloud Function 搜索数据时使用未指定的索引

    我构建了一个 Firebase 云函数 用于查找 IsNotificationEnabled 值等于 true 的用户 我的部分职能 export const sendPushNotification functions https onR
  • JavaScript:测试与执行

    我想知道检查字符串 例如邮件 密码等 的最佳方法是什么 i exec a vs i test a exec返回值 test true test 1 way var mail req body mail if check mail exec
  • 在 HTML5 iOS 7 / iOS 8 中显示十进制键盘

    经过几个小时的搜索后 我只是有一个简单的问题 是否有可能在网络浏览器输入字段中显示小数键盘 input type number 只显示数字 但我需要在左下角使用逗号或点 我尝试过任何事情 pattern step等等 但没有显示十进制键盘
  • Internet Explorer 9 是否会因数组和对象文字末尾的额外逗号而卡住?

    现代浏览器和 Node js 等环境允许您说 a 1 b 2 或 1 2 3 这在历史上一直是 Internet Explorer 的问题 Internet Explorer 9 中修复了此问题吗 对此有两种不同的答案 一种是对象初始值设定
  • 无法使用 HTML 设置未定义 jQuery UI 自动完成的属性“_renderItem”

    我使用以下代码将 jQuery UI 自动完成项呈现为 HTML 这些项目在自动完成控件中正确呈现 但我不断收到此 JavaScript 错误并且无法移动过去 Firefox 无法转换 JavaScript 参数 Chrome 无法设置未定

随机推荐

  • C语言密勒码的软件编码,密勒码的编码规则是什么?请画出代码序列11010010的密勒码波形?...

    相关题目与解析 CMI码的编码规则是什么 请画出代码序列11010010的CMI码波形 数字双相码的编码规则是什么 请画出代码序列11010010的双相码波形 简述双相码 曼彻斯特码 的编码规则并画出二进制比特序列1011010011的双相
  • k近邻算法的原理、示例与分析

    k近邻算法的原理 示例与分析 代码参考书籍 Python机器学习基础教程 Andreas C muller Sarah Guido著 张亮 译 北京 人民邮电出版社 2018 1 2019 6重印 实现环境 System Ubuntu se
  • Ubuntu查看CPU|GPU|型号等电脑配置

    电脑配置以及CPU 一个终极命令 可以包括以下命令显示的信息 cat proc cpuinfo alay ws sudo dmidecode grep Product Name Product Name Inspiron 3558 Prod
  • matlab以空间的点画球,3D空间画空洞小球Matlab程序

    3D空间画空洞小球Matlab程序 3D空间画空洞小球Matlab程序 有时候在三维空间中 需要画出很多的空洞小球 可以使用入戏的代码 clear all clc x y z sphere 100 hold on i 1 K 3 for c
  • 【C++入门】const和mutable关键字、常函数介绍

    1 常函数介绍 1 1 什么是常函数 1 常函数的定义 类的成员函数对类中任何成员不作修改而只能作访问的函数 简单来说 就是调用类的成员函数不会对类做任何修改 2 常函数的实现 常函数是依靠const关键字实现的 具体是在类中声明成员函数和
  • glDrawArrays,glDrawElements用法

    glDrawArrays 和 glDrawElements 的作用都是从一个数据数组中提取数据渲染基本图元 render primitives from array data 注 如果要 glDrawArrays 和 glDrawEleme
  • 面试题:【数据库二】mysql:explain解释器type关键字

    mysql的explain解释器的相关资源网上很多 这里我只记录一下我关心的Type列 type type字段的意思 当前sql扫描表的方法 type字段对应的value值 system gt const gt eq ref gt ref
  • Table master训练测试流程

    一 环境配置 参考 https github com JiaquanYe TableMASTER mmocr 由于依赖mmdetection 对版本的要求如下 Python 3 6 PyTorch 1 3 CUDA 9 2 GCC 5 在服
  • JavaScript 颜色转为十六进制

    const rgbToHex r g b gt 1 lt lt 24 r lt lt 16 g lt lt 8 b toString 16 slice 1 rgbToHex 60 115 255 运行结果
  • MobaXterm 突破14个session限制

    通常情况下 随着工作时间的增长 我们会保存许许多多的linux到本地的mobastream 然后当超过14个 就会被被限制 这个会让人很头疼 1 安装python 配置好环境变量 测试安装成功 2 基于项目进行解除限制 git clone
  • ListControl中判定双击哪一行哪一列

    NM DBLCLK消息 void CDBResultDlg OnNMDblclkListDb NMHDR pNMHDR LRESULT pResult int nRet 0 LVHITTESTINFO HitTestInfo LPNMITE
  • 代码审查(Code Review)

    1 代码审查概述 1 1 什么是代码审查 对计算机源代码系统化地审查 常用软件同行评审的方式进行 其目的是在找出及修正在软件开发初期未发现的错误 提升软件质量及开发者的技术 1 2 为什么要做代码审查 可以帮助提高代码质量 代码审查的初衷是
  • Geoscience knowledge graph in the big data era

    Geoscience knowledge graph in the big data era 记录我的学习心得 如有不妥 联系删除 Information 作者包括Chenghu ZHOU Hua WANG Chengshan WANG等人
  • 收到大量垃圾短信怎么办?如何屏蔽垃圾短信?

    手机要是突然收到大量垃圾短信 先不要急 原因可能是短信接口被刷 有人用大量短信轰炸来掩盖消费通知 什么意思呢 就是我们手机上各种购物APP或者第三方支付平台等会绑定银行卡 一些诈骗平台会通过大量短信轰炸来掩盖消费通知 就是银行卡被刷了 但是
  • vscoode中使用vue报错

    前言 为什么写了这篇笔记 因为今天我们学习了vue脚手架的知识 我最开始使用的是hb的命令控制台 他可以使用 我心血来潮 其实是因为vscode的美化太好了 想使用vscode打开vue的脚手架 所以我满怀期待的打开了vscode 1 报错
  • Hadoop总结之HDFS-Client端向HDFS中读写数据的流程

    一 Client向HDFS中存入数据 1 客户端通过Distributed FileSystem模块向NameNode请求上传文件 NameNode检查目标文件是否已存在 父目录是否存在 2 NameNode返回是否可以上传 不能上传会返回
  • 用Java编写,要求输出1~100内的素数。

    public class SuShu public static void main String args for int i 2 i lt 100 i boolean isSuShu true for int j 2 j
  • 接口(interface)和抽象类(abstract)的特点和区别

    接口 interface 和抽象类 abstract 的共同点和区别 进入这个话题之前我们先思考一下以下几个问题 1 我们为什要使用抽象类和接口 2 使用抽象类和接口有什么好处 3 我们在设计复杂程序时该怎么合理使用抽象类和接口 抽象类的特
  • huggingface tokenizers

    专注 NLP 的初创团队抱抱脸 hugging face 发布帮助自然语言处理过程中 更快的词语切分 tokenization 工具 Tokenizers 只要 20 秒就能编码 1GB 文本 功能多样 适用于 BPE byte level
  • Bootstrap typeahead使用问题记录及解决方案

    简单介绍 Bootstrap typeahead插件是用来完成输入框的自动完成 模糊搜索和建议提示的功能 支持ajax数据加载 类似于jquery的流行插件Autocomplete typeahead的使用方式有两种 通过数据属性字段的方式