<div>
<ul id="myTags"></ul>
<input type="submit" value="Submit">
</div>
$("#myTags").tagit({
tagSource: function(request,response){
$.ajax({
url:"../wenda/tagMatch",
data:{key:request.term},
dataType:'json',
success:function(data){
response ($.map(data,function(item){
//此处的item数据的格式是这样的{id:"49",text:"asp"}
return{value:item.text}
}))
}
})
}
});
当输入“你好”的时候,数据库没有匹配数据,此时是用户创建标签,传给后台的是文本;当输入“a”的时候,后台有数据,匹配了“asp”“apl”两个选项,ajax返回的数据格式是{id:"49",text:"asp"}
这种,当选择“asp”之后,submit时,后端希望能直接把所选标签的id值传过去(便于后期各种传参)。
如果全部传文本的话,后端需要先判断这个标签文本是否已经存储在数据库中
,不在,就新建一条数据{id:"50",text:"你好"},取出id值进行后期传递;如果已经存在,则直接取其对应的id值进行后期传递。
如果传id值的话,有id值的直接取值传递;没有id值的(新创建的标签)把文本存储在数据库,取出其id值传递。这样更便利一点,处理的逻辑少一些。
怎样才能把用户选择的标签的id值传给后端?用过这个插件的大牛请指教,谢谢!
思路就是把选中标签的id值先保存起来,然后把这个id值绑定在相应标签的属性上,最后提交时再取出来。
var lable_id;
$("#myTags").tagit({
autocomplete:{
source: function(request,response){
$.ajax({
url:tagMatchURL,
data:{key:request.term},
dataType:'json',
success:function(msg){
response ($.map(msg.data,function(item){
return{label:item.text,value:item.text,id:item.id};//把id值返回
}))
}
})
},
select: function(event,ui){
lable_id = ui.item.id;//把id值保存起来
$("#myTags").tagit('createTag',ui.item.value);
return false;
}
},
afterTagAdded: function(event,ui){
if(lable_id){
$(ui.tag).children('span').attr("lable_id",lable_id);//把id值绑定到<span>标签</span>上面
lable_id = null;
}else {//当标签不是通过下拉选择添加的时候(如按enter键、空格键添加等),向后台发送标签文本,创建新数据(后台有查重的处理)
var tagName = $(ui.tag).children('span').text();
$.ajax({
url:addTagURL,
data:{tagName:tagName},
dataType:'json',
success:function(msg){
$(ui.tag).children('span').attr("lable_id",msg.data.id);//返回新创建标签的id,如果是重复的标签则直接返回标签的id
}
})
}
}
});
最后提交时,可以把所有创建的标签的信息提取出来:
var tagCollection = [];
$(tagUlId).find('li:not(:last) > span').each(function(){
var tagInfo = {};
tagInfo.id = $(this).attr('lable_id');
tagInfo.text = $(this).text();
tagCollection.push(tagInfo);
});
return tagCollection;
把以上所有的过程进行了一次封装:
var czd_tag = {
insertTag: function(tagUlId,tagMatchURL,addTagURL){
var lable_id;
$(tagUlId).tagit({
tagLimit: 3,
placeholderText: "请输入标签,最多可输入3个,每个标签不超过12个字",
autocomplete:{
source: function(request,response){
$.ajax({
url:tagMatchURL,
data:{key:request.term},
dataType:'json',
success:function(msg){
response ($.map(msg.data,function(item){
return{label:item.text,value:item.text,id:item.id}
}))
}
})
},
select: function(event,ui){
lable_id = ui.item.id;
$("#myTags").tagit('createTag',ui.item.value);
return false;
}
},
afterTagAdded: function(event,ui){
if(lable_id){
$(ui.tag).children('span').attr("lable_id",lable_id);
lable_id = null;
}else {
var tagName = $(ui.tag).children('span').text();
$.ajax({
url:addTagURL,
data:{tagName:tagName},
dataType:'json',
success:function(msg){
$(ui.tag).children('span').attr("lable_id",msg.data.id);
}
})
}
}
});
},
getTagsInfo: function(tagUlId){
var tagCollection = [];
$(tagUlId).find('li:not(:last) > span').each(function(){
var tagInfo = {};
tagInfo.id = $(this).attr('lable_id');
tagInfo.text = $(this).text();
tagCollection.push(tagInfo);
})
return tagCollection;
},
removeAllTags: function(tagUlId){
$(tagUlId).tagit('removeAll');
return false;
}
/**
* DEMO
*
* <ul id="myTags" style="width:980px;margin:0 auto;"></ul>
* <span id="submit">submit</span><span class="cancel">取消</span>
* ------------------------------------------------------------------------------
* czd_tag.insertTag("#myTags","../wenda/tagMatch","../wenda/addTag");//调用插件
* $('#submit').click(function(){
* console.log(czd_tag.getTagsInfo("#myTags"));//获取标签的id、text值
* });
* $(".cancel").click(function(){
* czd_tag.removeAllTags("#myTags");//清除所有标签
* });
*/
};
以上的业务逻辑有一点问题是:创建新标签的过程是直接与服务器交互的,并不是最后一步提交时才与服务器通信。也就是说,当用户创建新标签时,数据库上就增加了一条数据,不论用户有没有最终提交问题或是发表文章。
比如,我发表一篇文章,创建了“哈哈”这个新标签,但是中途我又不想发表了,就把文章删除了。最终的结果就是服务器已经有这个标签了,但是没有任何与这个标签相关的内容。当下一次有人输入标签,输入“哈”的时候,就已经有了“哈哈”这个备选项,这会误导用户以为已经有人用过这个标签了,搜索这个标签相关的内容时,却发现又没有任何相关的内容……个人认为,这种处理流程还是有一点瑕疵的。
SF也有这个问题,只不过SF用了一个单独的“创建标签页面”,似乎是想把“创建新标签”这个过程与提问题、发文章分隔开,但,个人感觉还是没有避免上述的“会误导用户认为…”
如果提交时才把所有标签的文本信息一块传给服务器,就避免了上述歧义,但这时需要服务器端做一些查重、存新标签、取id值传递等一连串的业务逻辑,综合考虑还是选择了小概率事件的“让用户以为已经有人使用了这个标签”的做法。