一聚教程网:一个值得你收藏的教程网站

最新下载

热门教程

angularjs实现带查找筛选功能的select下拉框实例

时间:2017-01-12 编辑:简简单单 来源:一聚教程网

一.背景

对于select的下拉列表,像国家选择这样的功能,全世界那么多国家,一直拉滚动条多辛苦,眼睛也要盯着找,累!so,为优化用户体验,带查找功能的下拉框是非常非常有必要的。都知道jquery里有这样的插件,但我们用的是Angularjs,更希望用双向绑定,指令的方式优雅地解决这个问题。

分析:

   目标 在原来的
   问题

1.在selectSearch指令里,怎么获取到ng-options里的数据源,以及指定的value(option标签的value)和text(option标签里的text)字段名。

 2.用什么方式来筛选?是每次显示匹配项,隐藏不匹配项还是?按未邮?菰蠢锲ヅ洌?匦律?山岬恪?/p>

   思路

1.参考angular自带指令ng-options来获取数据源和value,text字段名。

特别说明,仅支持ng-options="obj.value as obj.text for obj in list"的普通形式,那些带分组的等等,暂不支持哈。

2.重新生成结点。(为什么这么选择,方便呀!)

二.具体实现

1.代码部分

1.1 js代码(请引先引入jquery,不然会报错)

 
 代码如下 复制代码
/**
 * 带筛选功能的下拉框
 * 使用方法 '+
    '
'+
    '
    '+
    // '
  • {{'+ valueTempl+'}}
  • '+
        ''+
        '
    '+
        '
    ',
       link: {
        pre:functionselectSearchPreLink(scope, element, attr, ctrls) {
     
         vartmplNode = $(this.template).first();
     
         varmodelName = attr.ngModel,
          name = attr.name? attr.name:('def'+Date.now());
         tmplNode.attr('id', name +'_chosecontianer');
     
         $animate.enter(tmplNode, element.parent(), element);
        },
        post:functionselectSearchPostLink(scope, element, attr, ctrls) {
         varchoseNode = element.next();//$('#'+attr.name +'_chosecontianer');
         choseNode.addClass(attr.class);
         element.addClass('chose-hide');
         // 当前选中项
         varngModelCtrl = ctrls[0];
         if(!ngModelCtrl || !attr.name)return;
     
         parseOptions(attr.ngOptions, element, scope);
         varrs = {};
     
         functionsetView() {
          varcurrentKey = ngModelCtrl.$modelValue;
          if(isNaN(currentKey) || !currentKey) {
           currentKey ='';
           choseNode.find('.j-view:first').text('请选择');
           choseNode.find('i').addClass('chose-hide');
          }
          if((currentKey +'').length > 0) {
           for(vari = 0, l = rs.idArray.length; i < l; i++) {
            if(rs.idArray[i] == currentKey) {
             choseNode.find('.j-view:first').text(rs.labelArray[i]);
             choseNode.find('i').removeClass('chose-hide');
             break;
            }
           }
          }
         }
     
         functionsetViewAndData() {
          if(!scope.options) {
           return;
          }
          rs = scope.options;
          setView();
         }
         scope.$watchCollection('options', setViewAndData);
         scope.$watch(attr.ngModel, setView);
     
     
         functiongetListNodes(value) {
          varnodes = [];
          value = $.trim(value);
          for(vari = 0, l = rs.labelArray.length; i < l; i++) {
           if(rs.labelArray[i].indexOf(value) > -1) {
            nodes.push($('
  • ').data('id', rs.idArray[i]).text(rs.labelArray[i]))
  •        }
          }
          returnnodes;
     
         }
         choseNode.on('keyup','.j-key',function() {
          // 搜索输入框keyup,重新筛选列表
          varvalue = $(this).val();
          choseNode.find('ul:first').empty().append(getListNodes(value));
          returnfalse;
         }).on('click',function() {
          choseNode.find('.j-drop').removeClass('chose-hide');
          if(choseNode.find('.j-view:first').text() !='请选择') {
           choseNode.find('i').removeClass('chose-hide');
          }
          choseNode.find('ul:first').empty().append(getListNodes(choseNode.find('.j-key').val()));
          returnfalse;
         }).on('click','ul>li',function() {
          var_this = $(this);
          ngModelCtrl.$setViewValue(_this.data('id'));
          ngModelCtrl.$render();
          choseNode.find('.j-drop').addClass('chose-hide');
          returnfalse;
     
         }).on('click','i',function() {
          ngModelCtrl.$setViewValue('');
          ngModelCtrl.$render();
          choseNode.find('.j-view:first').text('请选择');
          returnfalse;
     
         });
         $(document).on("click",function() {
          $('.j-drop').addClass('chose-hide');
          choseNode.find('i').addClass('chose-hide');
          returnfalse;
         });
     
        }
       }
      };
     })
     

    1.2 css代码(用less写的,以下是编译后的)

     
     代码如下 复制代码
    .chose-hide{
     position:absolute!important;
     top:-999em!important;
    }
    .chose-container {
     border:none!important;
     float:left;
     margin-right:40px;
     padding:0!important;
     position:relative;
    }
    .chose-container .chose-single {
     padding:6px12px;
     color:#333;
     width:100%;
     border:1pxsolid#eee;
     display: inline-block;
     height:30px;
    }
    .chose-container .chose-single::after {
     content:'';
     position:absolute;
     border-width:6px3px;
     border-style:solid;
     /* border-top-color: transparent; */
     border-left-color:transparent;
     border-right-color:transparent;
     border-bottom-color:transparent;
     right:8px;
     top:12px;
    }
    .chose-container .chose-single i {
     width:12px;
     float:right;
     right:8px;
     font-size:12px;
     height:12px;
     background-color:#eee;
    }
    .chose-container .chose-drop {
     width:195px;
     position:absolute;
     border:1pxsolid#eee;
     z-index:1000;
     background-color:#fff;
    }
    .chose-container .chose-search input[type='text'] {
     margin:0;
     padding-left:12px;
     width:100%;
     height:30px;
     border:1pxsolid#ccc;
     float:none;
    }
    .chose-container .chose-result {
     max-height:370px;
     overflow-y:scroll;
     overflow-x:hidden;
    }
    .chose-container .chose-result li {
     padding:5px12px;
     list-style-type:none;
    }
    .chose-container .chose-result li:hover {
     background-color:#e1e2e7;
    }
     

    1.3 使用及效果

     
     代码如下 复制代码
     请选择
     

    2.详细说明

    程序中的关键点是parseOptions函数,即前面分析里的问题1。parseOptions是参考ng-options的源码实现的,原来是想返回一个对象,这个对象里包含了数据源,但是在调试时,发现post函数中该函数返回对象里的数据为空,watch不到,所以改为用scope.options来存数据。

    热门栏目