angular.js - 多重自訂指令該怎麼寫?
曾经蜡笔没有小新
曾经蜡笔没有小新 2017-05-15 17:03:52
0
2
682

是這樣的,要建立一個登入用的東西,但卡在自訂指令上。
登入要求有一個帳號輸入框,一個密碼輸入框。

  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>
曾经蜡笔没有小新
曾经蜡笔没有小新

全部回覆(2)
phpcn_u1582

這個是解決IE8 placeholder相容的方法。
個人不建議你寫指令來完成你的需求,邏輯太亂。並不是說angular的亮點是指令,就要導出用指令。只是一個登陸介面,驗證邏輯寫到controller就可以了,如果都拿到指令寫,程式碼量至少翻倍,而且可讀性也不好。

过去多啦不再A梦

已棄學angular^^^

熱門教學
更多>
最新下載
更多>
網站特效
網站源碼
網站素材
前端模板