angular.js - 多重自定义指令应该怎么写?

浏览:45日期:2023-01-08

问题描述

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

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

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

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

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

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

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

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

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

主文件

<body ng-app='Main'> <form novalidate name='LoginForm'><p ng-form 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}|(13d|14[57]|15[^4,D]|17[678]|18d)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}}' ng-model='value' autocomplete='off'><label for='{{id}}'>{{placeholder}}</label>

问题解答

回答1:

这个是解决IE8 placeholder兼容的方法。个人不建议你写指令来完成你的需求,逻辑太乱。并不是说angular的亮点是指令,就要导出用指令。只是一个登陆界面,验证逻辑写到controller就可以了,如果都拿到指令写,代码量至少翻倍,而且可读性也不好。

回答2:

已弃学angular^^^

相关文章: