网站首页 » 前端开发 » JavaScript » AngularJS 指令实现自定义下拉框
上一篇:
下一篇:

AngularJS 指令实现自定义下拉框

前言

AngularJS 的时代已经接近尾,但依然使用它的项目还是不计其数,下面就来做一个自定义的下拉框。

效果走一波:

AngularJS 指令实现自定义下拉框

这个下拉框可以实现:

  • 禁用下拉框
  • 禁用指定下拉项
  • 选中高亮
  • 是否默认选中第一个
  • 是否要显示“全部”一项

自定义下拉框

样式代码
ul{
    padding: 0;
    margin:0;
    list-style:none;
}
.dj-select-box{
    position: relative;
    width: 200px;
    cursor: pointer;
}

.dj-select-box .dj-select-item{
    position: relative;
    height: 38px;
    line-height: 38px;
    border:1px solid #ccc;
    padding: 0 12px;
    user-select:none;
}

.dj-select-box .dj-select{
    position: absolute;
    top: 39px;
    border:1px solid #ccc;
    width: 100%;
    box-sizing: border-box;
    z-index: 99

}

.dj-select-box .dj-select li{
    padding: 12px;
    background: #fff;
    border-bottom: 1px solid #eee;
    user-select:none;
}

.dj-select-box .dj-select li:hover,
.dj-select-box .dj-select li.active
{
    background: #f5f5f5;
}

.dj-select-box.disabled,
.dj-select-box .dj-select li.item-disabled{
    color: #c0c4cc;
    cursor: not-allowed;
}

.dj-select-box .dj-select-item .icon{
	font-size: 14px;
    width: 24px;
    height: 24px;
    display: block;
    position: absolute;
    top: 50%;
    right: 12px;
    -webkit-transform: translateY(-50%) rotateZ(90deg);
    transform: translateY(-50%) rotateZ(90deg);
    -webkit-transition: all 0.3s ease 0s;
    transition: all 0.3s ease 0s
}

.dj-select-box .dj-select-item .icon.open{
    -webkit-transform: translateY(-50%) rotateZ(-90deg);
    transform: translateY(-50%) rotateZ(-90deg);
}

下面就是主要的 HTML 代码

HTML 代码
<!DOCTYPE html>
<html lang="en" ng-app="yk">
<head>
    <meta charset="UTF-8">
    <title>Document</title>
    <meta name="viewport" content="width=device-width, initial-scale=1.0, minimum-scale=1.0, maximum-scale=1.0, user-scalable=0, viewport-fit=cover">
    <link rel="stylesheet" href="index.css">
    <script src="http://yunkus.com/demo/lib/js/angular.min.js"></script>
    <script src="index.js"></script>
</head>
<body style="padding-top: 100px" ng-controller="ctrl">
    <h3>2018年世界杯</h3>
    <my-select default-select="defaultSelect" list="data" name-key="name" value-key="menuId" select-fn="selectItem($item)" show-all="showAll"></my-select>
    <h3>2018年世界杯</h3>
    <my-select disabled="disabled" default-select="defaultSelect" list="data2" name-key="name" value-key="menuId" select-fn="selectItem2($item)" show-all="showAll"></my-select>
</body>
</html>
JavaScript 代码
/*
* @Author: zhaoxixiong
* @Date:   2018-06-29 17:10:19
* @Last Modified by:   zhaoxixiong
* @Last Modified time: 2018-07-02 12:51:35
*/

var m = angular.module("yk",[]);
m.controller("ctrl",["$scope",function($scope){
$scope.tempName = {};
$scope.tempName2 = {};
$scope.showAll = false;
$scope.disabled = true;
$scope.defaultSelect = true;

$scope.data = [{
    name:"中国",
    menuId:1,
    disabled:true
},{
    name:"俄罗斯",
    menuId:2
},{
    name:"朝鲜",
    menuId:3,
},{
    name:"巴基斯坦",
    menuId:4
}]

$scope.data2 = [{
    name:"德国",
    menuId:1
},{
    name:"意大利",
    menuId:2
},{
    name:"法国",
    menuId:3
},{
    name:"英国",
    menuId:4
}]

$scope.selectItem = function(item){
    $scope.tempName = item;
    console.log(item);
}
$scope.selectItem2 = function(item){
    $scope.tempName2 = item;
}
}]);
m.directive("mySelect",function($document){
    return {
        restrict: 'EA',
        replace: true,
        scope:{
            disabled:"=?",      // 1 为禁用下拉,不带此参数则默认可以下拉
            showAll:"=?",       // 0 不显示“全部”选项,1 显示“全部”项
            defaultSelect:'=?', // 0 否,1 是,是否默认选中第一个
            list:'=',          // [必填项] 列表数据
            nameKey:'@',       // [必填项] 要显示在项中名称对应的 key
            valueKey:'@',      // 动态定义内部 “全部”项的 value 所对应的 key,如果没有全部项这个可不传
            selectFn:'&',      // 选中后的回调
        },
        template: '<div class="dj-select-box" ng-class="{\'disabled\':disabled}"><div ng-click="showSelect($event)" class="dj-select-item">{{showItem[nameKey]}}<span class="icon" ng-class="{\'open\':showStatus}"><svg xmlns="http://www.w3.org/2000/svg" focusable="false" viewBox="0 0 24 24"><path d="M8.59 16.34l4.58-4.59-4.58-4.59L10 5.75l6 6-6 6z"></path><svg xmlns="http://www.w3.org/2000/svg" focusable="false" viewBox="0 0 24 24"><path d="M8.59 16.34l4.58-4.59-4.58-4.59L10 5.75l6 6-6 6z"></path></svg></svg></span></div><ul class="dj-select" ng-if="showStatus"><li ng-class="{\'active\':showItem[valueKey] === item[valueKey],\'item-disabled\':item[\'disabled\']}" ng-click="selectItem($event,item)" ng-repeat="item in list">{{item[nameKey]}}</li></ul></div>',
        link:function(scope,el,attr){
            console.log(scope,el,attr);
            scope.showItem = {};
            scope.showStatus = false;
            scope.disabled = scope.disabled ? scope.disabled : false;
            scope.showAll = scope.showAll ? scope.showAll : false;
            scope.defaultSelect = scope.defaultSelect ? scope.defaultSelect : false;

            // 如果需要显示“全部”项,则初始化一个“全部”项
            if(scope.showAll === 1){
                scope.list.unshift({name:"全部"});
                scope.list[0][scope.valueKey] = "";
            }

            if(scope.defaultSelect){
                for(var i=0,item;item = scope.list[i++];){
                    if(!item.disabled){
                        scope.showItem = item;
                        break; // 跳出循环
                    }
                }
            }

            scope.showSelect = function(event){
                if(scope.disabled){
                    return;
                }
                scope.showStatus = !scope.showStatus;
                console.log(scope.showStatus);
                event.stopPropagation(); // 阻止冒泡
            }

            scope.selectItem = function(event,item){
                scope.showStatus = false; // 隐藏下拉选项
                if(item.disabled || item[scope.valueKey] === scope.showItem[scope.valueKey]){
                    return;
                }
                scope.selectFn({$item:item}); // 回调,往外传选中的对象
                scope.showItem = item; // 显示选中的内容(标题)
                event.stopPropagation(); // 阻止冒泡
            }

            // 点其他位置时隐藏下拉框
            $document.on("click",function(){
                scope.$apply(function(){
                    scope.showStatus = false;
                });
            })
        }
    }
});

在这里直接把 controller 和指令都放在一个文件里了,你可以根据自己的项目来进行归类。不管怎么样,下拉框的基本套路就是这样。

在写这个指令时有两个地方需要注意的:

第一个就是回调用参数的传入方式 scope.selectFn({$item:item});

第二个就是 $document.on(“click”,function(){}) 这里的作用就是当点了页面的其它地方时,下拉框也要隐藏起来。不过这里我们要使用 AngularJs 为我们提供的 $document 来进行响应,并且还需要在里面使用 scope.$apply() 来进行更新页面中的数据,不然 scope.showStatus 状态的更改是不会更新到页面中去的。

  • 微信扫一扫,赏我

  • 支付宝扫一扫,赏我

声明

原创文章,不经本站同意,不得以任何形式转载,如有不便,请多多包涵!

本文永久链接:http://yunkus.com/angularjs-directive-custom-select/

Leave a Reply

Your email address will not be published. Required fields are marked *

评论 END