@@ -20,6 +20,7 @@ import {
2020 input ,
2121 output ,
2222 signal ,
23+ TemplateRef ,
2324 ViewEncapsulation
2425} from '@angular/core' ;
2526import { takeUntilDestroyed } from '@angular/core/rxjs-interop' ;
@@ -31,11 +32,12 @@ import { NZ_SPACE_COMPACT_ITEM_TYPE, NZ_SPACE_COMPACT_SIZE, NzSpaceCompactItemDi
3132
3233import { NzInputAddonAfterDirective , NzInputAddonBeforeDirective } from './input-addon.directive' ;
3334import { NzInputPrefixDirective , NzInputSuffixDirective } from './input-affix.directive' ;
35+ import { NzInputPasswordDirective , NzInputPasswordIconDirective } from './input-password.directive' ;
3436import { NzInputDirective } from './input.directive' ;
3537import { NZ_INPUT_WRAPPER } from './tokens' ;
3638
3739@Component ( {
38- selector : 'nz-input-wrapper' ,
40+ selector : 'nz-input-wrapper,nz-input-password ' ,
3941 exportAs : 'nzInputWrapper' ,
4042 imports : [ NzIconModule , NzFormItemFeedbackIconComponent , NgTemplateOutlet ] ,
4143 template : `
@@ -87,7 +89,9 @@ import { NZ_INPUT_WRAPPER } from './tokens';
8789 @if (nzAllowClear()) {
8890 <span
8991 class="ant-input-clear-icon"
90- [class.ant-input-clear-icon-has-suffix]="nzSuffix() || suffix() || hasFeedback()"
92+ [class.ant-input-clear-icon-has-suffix]="
93+ nzSuffix() || suffix() || hasFeedback() || inputPasswordDir?.nzVisibilityToggle()
94+ "
9195 [class.ant-input-clear-icon-hidden]="!inputDir().value() || disabled() || readOnly()"
9296 role="button"
9397 tabindex="-1"
@@ -98,6 +102,23 @@ import { NZ_INPUT_WRAPPER } from './tokens';
98102 </ng-content>
99103 </span>
100104 }
105+ @if (inputPasswordDir && inputPasswordDir.nzVisibilityToggle()) {
106+ <span
107+ class="ant-input-password-icon"
108+ role="button"
109+ tabindex="-1"
110+ (click)="inputPasswordDir.toggleVisible()"
111+ >
112+ @if (inputPasswordIconTmpl(); as tmpl) {
113+ <ng-template
114+ [ngTemplateOutlet]="tmpl"
115+ [ngTemplateOutletContext]="{ $implicit: inputPasswordDir.nzVisible() }"
116+ />
117+ } @else {
118+ <nz-icon [nzType]="inputPasswordDir.nzVisible() ? 'eye' : 'eye-invisible'" nzTheme="outline" />
119+ }
120+ </span>
121+ }
101122 <ng-content select="[nzInputSuffix]">{{ nzSuffix() }}</ng-content>
102123 @if (hasFeedback() && status()) {
103124 <nz-form-item-feedback-icon [status]="status()" />
@@ -120,19 +141,23 @@ import { NZ_INPUT_WRAPPER } from './tokens';
120141 host : {
121142 '[class]' : 'class()' ,
122143 '[class.ant-input-disabled]' : 'disabled()' ,
144+ '[class.ant-input-password]' : 'inputPasswordDir' ,
123145 '[class.ant-input-affix-wrapper-textarea-with-clear-btn]' : 'nzAllowClear() && isTextarea()'
124146 }
125147} )
126148export class NzInputWrapperComponent {
127149 private readonly focusMonitor = inject ( FocusMonitor ) ;
128150
151+ protected readonly inputPasswordDir = inject ( NzInputPasswordDirective , { self : true , optional : true } ) ;
152+
129153 protected readonly inputRef = contentChild . required ( NzInputDirective , { read : ElementRef } ) ;
130154 protected readonly inputDir = contentChild . required ( NzInputDirective ) ;
131155
132156 protected readonly prefix = contentChild ( NzInputPrefixDirective ) ;
133157 protected readonly suffix = contentChild ( NzInputSuffixDirective ) ;
134158 protected readonly addonBefore = contentChild ( NzInputAddonBeforeDirective ) ;
135159 protected readonly addonAfter = contentChild ( NzInputAddonAfterDirective ) ;
160+ protected readonly inputPasswordIconTmpl = contentChild ( NzInputPasswordIconDirective , { read : TemplateRef } ) ;
136161
137162 readonly nzAllowClear = input ( false , { transform : booleanAttribute } ) ;
138163 readonly nzPrefix = input < string > ( ) ;
@@ -151,7 +176,7 @@ export class NzInputWrapperComponent {
151176
152177 protected readonly hasPrefix = computed ( ( ) => ! ! this . nzPrefix ( ) || ! ! this . prefix ( ) ) ;
153178 protected readonly hasSuffix = computed (
154- ( ) => ! ! this . nzSuffix ( ) || ! ! this . suffix ( ) || this . nzAllowClear ( ) || this . hasFeedback ( )
179+ ( ) => ! ! this . nzSuffix ( ) || ! ! this . suffix ( ) || this . nzAllowClear ( ) || this . hasFeedback ( ) || this . inputPasswordDir
155180 ) ;
156181 protected readonly hasAffix = computed ( ( ) => this . hasPrefix ( ) || this . hasSuffix ( ) ) ;
157182 protected readonly hasAddonBefore = computed ( ( ) => ! ! this . nzAddonBefore ( ) || ! ! this . addonBefore ( ) ) ;
0 commit comments