44 */
55
66import { FocusMonitor } from '@angular/cdk/a11y' ;
7- import { Direction , Directionality } from '@angular/cdk/bidi' ;
7+ import { Directionality } from '@angular/cdk/bidi' ;
88import {
9- ChangeDetectorRef ,
9+ ChangeDetectionStrategy ,
1010 Component ,
11+ DestroyRef ,
1112 ElementRef ,
12- Input ,
13- OnDestroy ,
14- OnInit ,
1513 ViewEncapsulation ,
14+ afterNextRender ,
1615 booleanAttribute ,
17- forwardRef
16+ computed ,
17+ forwardRef ,
18+ inject ,
19+ input ,
20+ linkedSignal ,
21+ signal
1822} from '@angular/core' ;
23+ import { takeUntilDestroyed , toSignal } from '@angular/core/rxjs-interop' ;
1924import { ControlValueAccessor , NG_VALUE_ACCESSOR } from '@angular/forms' ;
20- import { Subject } from 'rxjs' ;
21- import { takeUntil } from 'rxjs/operators' ;
2225
2326import { OnChangeType , OnTouchedType } from 'ng-zorro-antd/core/types' ;
2427
2528import { NzCheckboxComponent } from './checkbox.component' ;
29+ import { NZ_CHECKBOX_GROUP } from './tokens' ;
2630
27- export interface NzCheckBoxOptionInterface {
31+ export interface NzCheckboxOption {
2832 label : string ;
29- value : string ;
30- checked ?: boolean ;
33+ value : string | number ;
3134 disabled ?: boolean ;
3235}
3336
37+ /**
38+ * @deprecated Deprecated in v19.0.0. Please use {@link NzCheckboxOption} to instead.
39+ */
40+ export type NzCheckBoxOptionInterface = NzCheckboxOption ;
41+
3442@Component ( {
3543 selector : 'nz-checkbox-group' ,
3644 exportAs : 'nzCheckboxGroup' ,
37- preserveWhitespaces : false ,
38- encapsulation : ViewEncapsulation . None ,
45+ imports : [ NzCheckboxComponent ] ,
3946 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>
5159 ` ,
5260 providers : [
5361 {
5462 provide : NG_VALUE_ACCESSOR ,
5563 useExisting : forwardRef ( ( ) => NzCheckboxGroupComponent ) ,
5664 multi : true
65+ } ,
66+ {
67+ provide : NZ_CHECKBOX_GROUP ,
68+ useExisting : forwardRef ( ( ) => NzCheckboxGroupComponent )
5769 }
5870 ] ,
5971 host : {
6072 class : 'ant-checkbox-group' ,
61- '[class.ant-checkbox-group-rtl]' : `dir === 'rtl'`
73+ '[class.ant-checkbox-group-rtl]' : `dir() === 'rtl'`
6274 } ,
63- imports : [ NzCheckboxComponent ]
75+ encapsulation : ViewEncapsulation . None ,
76+ changeDetection : ChangeDetectionStrategy . OnPush
6477} )
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 ) ;
96110 } ) ;
97-
98- this . directionality . change ?. pipe ( takeUntil ( this . destroy$ ) ) . subscribe ( ( direction : Direction ) => {
99- this . dir = direction ;
100- this . cdr . detectChanges ( ) ;
101111 } ) ;
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 ( ) ;
110112 }
111113
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 ) ;
115116 }
116117
117118 registerOnChange ( fn : OnChangeType ) : void {
@@ -123,8 +124,36 @@ export class NzCheckboxGroupComponent implements ControlValueAccessor, OnInit, O
123124 }
124125
125126 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 ;
129131 }
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+ } ) ;
130159}
0 commit comments