是这样的,要创建一个登录用的东西,但卡在自定义指令上。
登录要求有一个账号输入框,一个密码输入框。
因为要兼容IE8,所以PLACEHOLDER属性不能直接用。需要使用自定义指令来完成。
账号可以是手机,也可以是邮箱,也可以是普通账号。
邮箱需要自动生成后缀,所以也需要自定义指令。可以设定是否需要在输入了@
之后再显示邮箱提示。
账号需要可以自己验证,这又要引入自定义指令来写验证(从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>
Il s'agit d'une solution pour la compatibilité des espaces réservés IE8.
Personnellement, je ne vous recommande pas d'écrire des instructions pour répondre à vos besoins, la logique est trop déroutante. Cela ne signifie pas que le point culminant d'Angular sont les instructions, et les instructions doivent être exportées. Il ne s'agit que d'une interface de connexion et la logique de vérification peut être écrite sur le contrôleur. Si vous recevez des instructions pour l'écrire, la quantité de code doublera au moins et la lisibilité ne sera pas bonne.
École abandonnée^^^