angular.js - 多重自定义指令应该怎么写?
曾经蜡笔没有小新
曾经蜡笔没有小新 2017-05-15 17:03:52
0
2
668

是这样的,要创建一个登录用的东西,但卡在自定义指令上。
登录要求有一个账号输入框,一个密码输入框。

  1. 因为要兼容IE8,所以PLACEHOLDER属性不能直接用。需要使用自定义指令来完成。

  2. 账号可以是手机,也可以是邮箱,也可以是普通账号。

  3. 邮箱需要自动生成后缀,所以也需要自定义指令。可以设定是否需要在输入了@之后再显示邮箱提示。

  4. 账号需要可以自己验证,这又要引入自定义指令来写验证(从angular官网上看到的方法,自定义验证器)。

现在要使用多重自定义指令,来完成这个东西(如果大家有更好的办法,也可以不用这个,请告诉我,谢谢)。

我的想法是,先定义一个自定义指令,可以让它的PLACEHOLDER在需要的时候显示出来。然后在此基础上定义一个EMAIL指令,当输入账号的时候,自动给它加上各种域名的后缀,以供选择。最后再在这个基础上,定义一个PASSPORT指令,可以判断当前输入的内容是不是可用的账号(手机/邮箱/普通用户名)。

但是问题来了,如果要在同一个作用域中使用多个这种自定义指令的话,指令就必须是分离作用域,但是这三层的自定义指令,没办法都定分离作用域,会报错。如果要使各个此种指令分离的话,想到使用ng-repeat,但是ng-repeat生成的class又没办法在生成之后,自动编译成正常的指令……

我知道我说的有点儿乱,如果大家有别的好办法,请交流一下,谢谢。最后上代码……

主文件

<body ng-app="Main">

    <form novalidate name="LoginForm">
        <p ng-form class="dir-text-placeholder dir-text-email dir-text-passport" 
            ng-init="needAt=true; 
            name='user_passport'; 
            id='user_passport'; 
            placeholder='用户名/邮箱/手机';">
        </p>
    </form>

</body>
angular.module('Main', [])
    .directive('dirTextPlaceholder', [function () {
        return {
            restrict: 'C',
            priority:111,
            controller:function(){
                console.info('in textPlaceholder')
            },
            link: function (scope, iElement, iAttrs) {
                var input=iElement.find('input').eq(0);
                scope.$watch("value",function(newValue,oldValue){
                    if(!!newValue && !oldValue) 
                        input.addClass("chi-full").removeClass("chi-empty");
                    else if(!newValue && !!oldValue) 
                        input.addClass("chi-empty").removeClass("chi-full");
                });
            },
            templateUrl:"text-placeholder.html"
        };
    }])
    .directive('dirTextEmail', ['$compile','$timeout',function ($compile,$timeout) {
        var hosts='126.com|163.com|qq.com|sina.com|yeah.net'.split('|');
        return {
            restrict: 'C',
            priority:11,
            require: '?dirTextPlaceholder',
            controller:function(){
                console.info('in textEmail')
            },
            link: function (scope, iElement, iAttrs) {
                iElement.append("<ul></ul>")
                var input=iElement.find('input').eq(0),
                    ul=iElement.find('ul').eq(0),
                    li=angular.element('<li ng-repeat="email in emails | filter:host" ng-click="setEmail(email)">{{email}}</li>');
                $compile(li)(scope);
                ul.append(li);
                scope.$watch("value",function(newValue){
                    if(newValue===undefined) return false;
                    var indexAt=newValue.indexOf('@');
                    if(scope.needAt && !~indexAt) return false;
                    scope.host=newValue.substring(indexAt);
                    var passport=newValue.substring(0,indexAt);
                    var emails=[];
                    for(var n=0;n<hosts.length;n++) emails.push(passport+'@'+hosts[n]);
                    scope.emails=emails;
                    emails=null;
                    $timeout(function(){
                        if(ul.children().length==1 && ul.children().eq(0).html()==newValue)
                            ul.hide();
                        else ul.show();
                    });
                });
                scope.setEmail=function(email){
                    scope.value=email;
                }
            }
        };
    }])
    .directive('dirTextPassport', ['$rootScope',function ($rootScope) {
        return {
            restrict: 'C',
            priority:1,
            require: '?dirTextEmail',
            controller: function(){
                console.info('in textPassport')
            },
            link: function (scope, iElement, iAttrs) {
                var ptr=/^\w[-\w.+]*@([A-Za-z0-9][-A-Za-z0-9]+\.)+[A-Za-z]{2,14}|(13\d|14[57]|15[^4,\D]|17[678]|18\d)\d{8}|170[059]\d{7}$/,
                    input=iElement.find('input').eq(0),
                    controller=angular.element(iElement).scope();
                console.log($rootScope)
                //写到这儿的时候,想起来,账号跟密码要放在同一个作用域下,
                //所以第一个指令不采用分离作用域是不行的,但是分离之后,
                //后续的跟它作用在同一DOM上的其它指令又不能再用分离作用域,我就不会了……
            }
        };
    }])

模板文件text-placeholder.html

<input type="{{type}}" name="{{name}}" id="{{id}}" ng-model="value" autocomplete="off">
<label for="{{id}}">{{placeholder}}</label>
曾经蜡笔没有小新
曾经蜡笔没有小新

reply all(2)
phpcn_u1582

This is a solution for IE8 placeholder compatibility.
Personally, I don’t recommend that you write instructions to complete your needs. The logic is too confusing. It does not mean that the highlight of angular is instructions, and instructions must be exported. It is just a login interface, and the verification logic can be written to the controller. If you get instructions to write it, the amount of code will at least double, and the readability will not be good.

过去多啦不再A梦

Have abandoned school^^^

Latest Downloads
More>
Web Effects
Website Source Code
Website Materials
Front End Template
About us Disclaimer Sitemap
php.cn:Public welfare online PHP training,Help PHP learners grow quickly!