ng-type / show-password directive on `<input>

2020-02-29 00:06发布

问题:

We can use data-binding on input elements like this:

<input type="{{ showPassword ? 'text' : 'password' }}" name="password">

But this has similar problems as using data-binding on a href attribute (see ngHref). This way there is an input element in the dom with the type {{ showPassword ? 'text' : 'password' }} until angular loads. It looks convenient to have an ngType directive much like ngHref, what could be used this way:

<input type="password" ng-type="{{ showPassword ? 'text' : 'password' }}" name="password">

Is there any other way to do it? Do I have to implement this ngType thing?

回答1:

Custom directive that changes the <input> type:

To show or hide the password use a custom directive:

app.directive("showPassword", function() { 
    return function linkFn(scope, elem, attrs) {
        scope.$watch(attrs.showPassword, function(newValue) {
            if (newValue) {
                elem.attr("type", "text");
            } else {
                elem.attr("type", "password");
            };
        });
    };
});

Usage

 <input type=password show-password="showPassword" 
        ng-model="thePassword">

The show-password directive watches the defined scope variable and changes the input to type=text when truthy and back to type=password when falsey.

The DEMO

angular.module("myApp",[])
.directive("showPassword", function() { 
    return function linkFn(scope, elem, attrs) {
        scope.$watch(attrs.showPassword, function(newValue) {
            if (newValue) {
                elem.attr("type", "text");
            } else {
                elem.attr("type", "password");
            };
        });
    };
})
<script src="//unpkg.com/angular/angular.js"></script>
<div ng-app='myApp'>

    <button ng-click="showPassword = true">Show Password</button><br>
    <button ng-click="showPassword = false">Hide Password</button><br>
    
    <input type=password show-password="showPassword" 
           ng-model="thePassword">
    <hr>
    PASSWORD == {{thePassword}}
</div>