使用bootstrip Typeahead 过程还是蛮曲折的,因为充斥在网络上的博文大多是以前版本的js支持,新版本则有些参数不支持,而且因为版本的不同,参数变化,和方法的使用区别还是蛮大的,造成了一定的误解。
Typeahead分了两大版本 一个是bootstrip3-Typeahead,一个则是Teitter上的Typeahead上的,当然这个也是基于bootstrip框架的。由于现在bootstrip优秀的后台框架,很华丽,所以越来越多人使用,但就我个人而言,许多地方还是EasyUI做的更好,当然EasyUI的界面跟bootstrip还是有一定的差距的。
git地址:https://github.com/twitter/typeahead.js
首页:http://twitter.github.io/typeahead.js/ (这里可以下载最新的Typeahead),
当前使用的typeahead版本是:v0.10.5,基于JQuery 1.x 、2.x 和bootstrap 3。
先提供一个很好的博文,
http://blog.64cm.com/post/2014/08/13/%E4%BD%BF%E7%94%A8bootstrap-typeahead%E6%8F%92%E4%BB%B6
我也是看这个博文才更深一步的了解typeahead,但是这个虽然提供的例子很多,但都是只能用来测试的例子,并不能直接移植到我们的项目中,因为我们的项目并不是只要能够进行一些简单的操作就可以了,还有很多复杂的其他操作,这样就又造成一些问题,这里我慢慢叙述我的失败经历和成功过程。
(只演示AJAX动态从后台获取数据,实际上大部分都是这样实现的,用预加载那个,有缓存,很不友好的。当然对于那种经常不发生变化的数据,可以考虑使用prefetch)
最基础的写法:(Remote)
<div class="example">
<h2>Ajax及时获取数据示例</h2>
<div id="ajax-remote-example">
<input class="typeahead" id="txtSearchRecipient" type="text" placeholder="请输入城市">
</div>
</div>
//远程数据源
var remote_cities = new Bloodhound({
datumTokenizer: Bloodhound.tokenizers.obj.whitespace('CityName'),
queryTokenizer: Bloodhound.tokenizers.whitespace,
// 在文本框输入字符时才发起请求
remote: '/ajax/GetCities?q=%QUERY'
});
remote_cities.initialize();
$('#ajax-remote-example .typeahead').typeahead(null, {
name: 'cities',
displayKey: 'CityName',
source: remote_cities.ttAdapter()
});
在后台按照自己的逻辑去匹配最终获取一串json,
return Json(list, JsonRequestBehavior.AllowGet);
不敢把方法名上传,毕竟是公司财产,毕竟刚刚毕业的大学生,在公司中难免战战兢兢。重点是最后一句话。当然了,若是你自己有专门的工具类可以直接转化,则不必这么麻烦。
接下来就是最坑人的地方了,引入js:
由于之前已经引入了jq,bootstrap,就不必在引入了,typeahead中的js为必须的js,那个respond.js为vs自动为项目创建,在Script目录中。没有可以下一个,这个对版本没有要求。
在母版页引入,但是引入位置是不同的,typeahead文件夹下的js文件是通过RenderSection,在使用页面中引用的:(看清head和body的位置)
然后引用页面的写法:
很清晰,在头部正常引用模板页,在文档尾部使用
@section scripts包裹,重新引用jq和bootstrip,并引入typeahead的必须js。
然后才能把一开始js写进去,才能生效。
这个的用法,很少有博文去说明,可能是他们用的框架模板不一样,可能是他们觉得太简单,不值得一提,但是我对这个接触很少,这个流程也是我琢磨了好久才实现的,贴出来希望能够帮助到那些和我一样的道友们。
到这里一般的测试是可以了,但是一般我们使用这个,并不只要传递一个值,而是要将id和name同时传递过来。我们模拟一个需求:
通过选择code,将该code对应的model中所有的值自动填入到其他输入框。
这样我们有三中实现方式,但是无论哪一种实现方式,以上的测试都是不能满足的:
1.获取code框的失去焦点事件,然后将code传入后台,根据条件取出model,然后装载
2.将code对应的id取出(假设code不是唯一识别列),然后通过typeahead选中事件,通过ajax取出model中的所有数据,然后装载。
3.在typeahead加载时,直接将model传入list中,然后通过typeahead选中事件,获取model中除了code列的其他值。
很明显第一种做很不好,且不说code能不能区别出model,单说失去焦点的判别,这个让操作很不友好,若是一般公司还好,对于在外面工作的人使用来说,很不好。
后两种则是很不错的方式,第二种可以减少typeahead耗费在加载list时的资源,而第三种则可以很快的将结果装载到其他输入框,这其中的取舍根据项目的不同而确定。
这里我用的是后者,也就是后台传过来的list里面是一个很大的Model,装载有Code对应的Model的所有数据,如果你的Model数据很大,又想使用第三种,则可以通过限定最大显示数目来进一步优化。这个不多提了,具体的使用在你们项目中,可以斟酌使用。
这里的唯一难点就是Typeahead的选中事件了。网上很多博文的选中事件,都是对应其typeahead的版本的,而我们版本的选中事件写法为:
jQuery(function () {
var remote_code = new Bloodhound({
datumTokenizer: Bloodhound.tokenizers.obj.whitespace('consigneeCode'),
queryTokenizer: Bloodhound.tokenizers.whitespace,
remote: '/ControllerName/text?query=%QUERY'
});
remote_code.initialize();
$('#txtSearchRecipient').typeahead(null, {
name: 'consignee',
displayKey: 'consigneeCode',
id: 'Id',
source: remote_code.ttAdapter()
}).on('typeahead:selected', function ($e, datum) {
$('#hfConsigneeId').val(datum["consigneeId"]);
//....其他数据的装载雷同
});
其他用法,可以去阅读git上的文档。(因为是公司内部页面,没办法将成品展示)