4
4
*/
5
5
6
6
import { FocusMonitor } from '@angular/cdk/a11y' ;
7
- import { Direction , Directionality } from '@angular/cdk/bidi' ;
7
+ import { Directionality } from '@angular/cdk/bidi' ;
8
8
import {
9
- ChangeDetectorRef ,
9
+ ChangeDetectionStrategy ,
10
10
Component ,
11
+ DestroyRef ,
11
12
ElementRef ,
12
- Input ,
13
- OnDestroy ,
14
- OnInit ,
15
13
ViewEncapsulation ,
14
+ afterNextRender ,
16
15
booleanAttribute ,
17
- forwardRef
16
+ computed ,
17
+ forwardRef ,
18
+ inject ,
19
+ input ,
20
+ linkedSignal ,
21
+ signal
18
22
} from '@angular/core' ;
23
+ import { takeUntilDestroyed , toSignal } from '@angular/core/rxjs-interop' ;
19
24
import { ControlValueAccessor , NG_VALUE_ACCESSOR } from '@angular/forms' ;
20
- import { Subject } from 'rxjs' ;
21
- import { takeUntil } from 'rxjs/operators' ;
22
25
23
26
import { OnChangeType , OnTouchedType } from 'ng-zorro-antd/core/types' ;
24
27
25
28
import { NzCheckboxComponent } from './checkbox.component' ;
29
+ import { NZ_CHECKBOX_GROUP } from './tokens' ;
26
30
27
- export interface NzCheckBoxOptionInterface {
31
+ export interface NzCheckboxOption {
28
32
label : string ;
29
- value : string ;
30
- checked ?: boolean ;
33
+ value : string | number ;
31
34
disabled ?: boolean ;
32
35
}
33
36
37
+ /**
38
+ * @deprecated Deprecated in v19.0.0. Please use {@link NzCheckboxOption} to instead.
39
+ */
40
+ export type NzCheckBoxOptionInterface = NzCheckboxOption ;
41
+
34
42
@Component ( {
35
43
selector : 'nz-checkbox-group' ,
36
44
exportAs : 'nzCheckboxGroup' ,
37
- preserveWhitespaces : false ,
38
- encapsulation : ViewEncapsulation . None ,
45
+ imports : [ NzCheckboxComponent ] ,
39
46
template : `
40
- @for (option of options; track option.value) {
41
- <label
42
- nz-checkbox
43
- class="ant-checkbox-group-item"
44
- [nzDisabled]="option.disabled || nzDisabled"
45
- [nzChecked]="option.checked!"
46
- (nzCheckedChange)="onCheckedChange(option, $event)"
47
- >
48
- <span>{{ option.label }}</span>
49
- </label>
50
- }
47
+ <ng-content>
48
+ @for (option of normalizedOptions(); track option.value) {
49
+ <label
50
+ nz-checkbox
51
+ [nzValue]="option.value"
52
+ [nzName]="nzName()"
53
+ [nzDisabled]="option.disabled || finalDisabled()"
54
+ >
55
+ {{ option.label }}
56
+ </label>
57
+ }
58
+ </ng-content>
51
59
` ,
52
60
providers : [
53
61
{
54
62
provide : NG_VALUE_ACCESSOR ,
55
63
useExisting : forwardRef ( ( ) => NzCheckboxGroupComponent ) ,
56
64
multi : true
65
+ } ,
66
+ {
67
+ provide : NZ_CHECKBOX_GROUP ,
68
+ useExisting : forwardRef ( ( ) => NzCheckboxGroupComponent )
57
69
}
58
70
] ,
59
71
host : {
60
72
class : 'ant-checkbox-group' ,
61
- '[class.ant-checkbox-group-rtl]' : `dir === 'rtl'`
73
+ '[class.ant-checkbox-group-rtl]' : `dir() === 'rtl'`
62
74
} ,
63
- imports : [ NzCheckboxComponent ]
75
+ encapsulation : ViewEncapsulation . None ,
76
+ changeDetection : ChangeDetectionStrategy . OnPush
64
77
} )
65
- export class NzCheckboxGroupComponent implements ControlValueAccessor , OnInit , OnDestroy {
66
- onChange : OnChangeType = ( ) => { } ;
67
- onTouched : OnTouchedType = ( ) => { } ;
68
- options : NzCheckBoxOptionInterface [ ] = [ ] ;
69
- @Input ( { transform : booleanAttribute } ) nzDisabled = false ;
70
-
71
- dir : Direction = 'ltr' ;
72
-
73
- private destroy$ = new Subject < void > ( ) ;
74
- private isNzDisableFirstChange : boolean = true ;
75
-
76
- onCheckedChange ( option : NzCheckBoxOptionInterface , checked : boolean ) : void {
77
- option . checked = checked ;
78
- this . onChange ( this . options ) ;
79
- }
80
-
81
- constructor (
82
- private elementRef : ElementRef ,
83
- private focusMonitor : FocusMonitor ,
84
- private cdr : ChangeDetectorRef ,
85
- private directionality : Directionality
86
- ) { }
87
-
88
- ngOnInit ( ) : void {
89
- this . focusMonitor
90
- . monitor ( this . elementRef , true )
91
- . pipe ( takeUntil ( this . destroy$ ) )
92
- . subscribe ( focusOrigin => {
93
- if ( ! focusOrigin ) {
94
- Promise . resolve ( ) . then ( ( ) => this . onTouched ( ) ) ;
95
- }
78
+ export class NzCheckboxGroupComponent implements ControlValueAccessor {
79
+ private onChange : OnChangeType = ( ) => { } ;
80
+ private onTouched : OnTouchedType = ( ) => { } ;
81
+ private isDisabledFirstChange = true ;
82
+ private readonly directionality = inject ( Directionality ) ;
83
+
84
+ readonly nzName = input < string | null > ( null ) ;
85
+ readonly nzDisabled = input ( false , { transform : booleanAttribute } ) ;
86
+ readonly nzOptions = input < NzCheckboxOption [ ] > ( [ ] ) ;
87
+ readonly value = signal < Array < NzCheckboxOption [ 'value' ] > | null > ( null ) ;
88
+ readonly finalDisabled = linkedSignal ( ( ) => this . nzDisabled ( ) ) ;
89
+
90
+ protected readonly dir = toSignal ( this . directionality . change , { initialValue : this . directionality . value } ) ;
91
+ protected readonly normalizedOptions = computed ( ( ) => normalizeOptions ( this . nzOptions ( ) ) ) ;
92
+
93
+ constructor ( ) {
94
+ const elementRef = inject ( ElementRef ) ;
95
+ const focusMonitor = inject ( FocusMonitor ) ;
96
+ const destroyRef = inject ( DestroyRef ) ;
97
+
98
+ afterNextRender ( ( ) => {
99
+ focusMonitor
100
+ . monitor ( elementRef , true )
101
+ . pipe ( takeUntilDestroyed ( destroyRef ) )
102
+ . subscribe ( focusOrigin => {
103
+ if ( ! focusOrigin ) {
104
+ this . onTouched ( ) ;
105
+ }
106
+ } ) ;
107
+
108
+ destroyRef . onDestroy ( ( ) => {
109
+ focusMonitor . stopMonitoring ( elementRef ) ;
96
110
} ) ;
97
-
98
- this . directionality . change ?. pipe ( takeUntil ( this . destroy$ ) ) . subscribe ( ( direction : Direction ) => {
99
- this . dir = direction ;
100
- this . cdr . detectChanges ( ) ;
101
111
} ) ;
102
-
103
- this . dir = this . directionality . value ;
104
- }
105
-
106
- ngOnDestroy ( ) : void {
107
- this . focusMonitor . stopMonitoring ( this . elementRef ) ;
108
- this . destroy$ . next ( ) ;
109
- this . destroy$ . complete ( ) ;
110
112
}
111
113
112
- writeValue ( value : NzCheckBoxOptionInterface [ ] ) : void {
113
- this . options = value ;
114
- this . cdr . markForCheck ( ) ;
114
+ writeValue ( value : Array < string | number > | null ) : void {
115
+ this . value . set ( value ) ;
115
116
}
116
117
117
118
registerOnChange ( fn : OnChangeType ) : void {
@@ -123,8 +124,36 @@ export class NzCheckboxGroupComponent implements ControlValueAccessor, OnInit, O
123
124
}
124
125
125
126
setDisabledState ( disabled : boolean ) : void {
126
- this . nzDisabled = ( this . isNzDisableFirstChange && this . nzDisabled ) || disabled ;
127
- this . isNzDisableFirstChange = false ;
128
- this . cdr . markForCheck ( ) ;
127
+ if ( ! this . isDisabledFirstChange ) {
128
+ this . finalDisabled . set ( disabled ) ;
129
+ }
130
+ this . isDisabledFirstChange = false ;
129
131
}
132
+
133
+ onCheckedChange ( optionValue : NzCheckboxOption [ 'value' ] , checked : boolean ) : void {
134
+ if ( this . finalDisabled ( ) ) return ;
135
+
136
+ this . value . update ( value => {
137
+ if ( checked ) {
138
+ return value ?. concat ( optionValue ) || [ optionValue ] ;
139
+ } else {
140
+ return value ?. filter ( val => val !== optionValue ) || [ ] ;
141
+ }
142
+ } ) ;
143
+
144
+ this . onChange ( this . value ( ) ) ;
145
+ }
146
+ }
147
+
148
+ function normalizeOptions ( value : string [ ] | number [ ] | NzCheckboxOption [ ] ) : NzCheckboxOption [ ] {
149
+ return value . map ( item => {
150
+ if ( typeof item === 'string' || typeof item === 'number' ) {
151
+ return {
152
+ label : `${ item } ` ,
153
+ value : item
154
+ } ;
155
+ }
156
+
157
+ return item ;
158
+ } ) ;
130
159
}
0 commit comments