Skip to content

Commit 33fe53d

Browse files
authored
fix(module:segmented): fix error with the FormControl first change (#9039)
1 parent d36a461 commit 33fe53d

File tree

2 files changed

+58
-14
lines changed

2 files changed

+58
-14
lines changed

components/segmented/segmented-item.component.ts

+18-13
Original file line numberDiff line numberDiff line change
@@ -8,9 +8,11 @@ import {
88
ChangeDetectionStrategy,
99
ChangeDetectorRef,
1010
Component,
11+
DestroyRef,
1112
ElementRef,
1213
inject,
1314
Input,
15+
OnInit,
1416
ViewEncapsulation
1517
} from '@angular/core';
1618
import { takeUntilDestroyed } from '@angular/core/rxjs-interop';
@@ -50,7 +52,7 @@ import { NzSegmentedService } from './segmented.service';
5052
changeDetection: ChangeDetectionStrategy.OnPush,
5153
encapsulation: ViewEncapsulation.None
5254
})
53-
export class NzSegmentedItemComponent {
55+
export class NzSegmentedItemComponent implements OnInit {
5456
@Input() nzIcon?: string;
5557
@Input() nzValue!: string | number;
5658
@Input() nzDisabled?: boolean;
@@ -59,17 +61,25 @@ export class NzSegmentedItemComponent {
5961

6062
private readonly service = inject(NzSegmentedService);
6163

62-
constructor() {
63-
const cdr = inject(ChangeDetectorRef);
64-
const elementRef = inject(ElementRef);
64+
constructor(
65+
private cdr: ChangeDetectorRef,
66+
private elementRef: ElementRef,
67+
private destroyRef: DestroyRef
68+
) {
69+
this.service.disabled$.pipe(takeUntilDestroyed()).subscribe(disabled => {
70+
this.nzDisabled = disabled;
71+
this.cdr.markForCheck();
72+
});
73+
}
6574

75+
ngOnInit(): void {
6676
this.service.selected$
6777
.pipe(
6878
tap(value => {
6979
this.isChecked = false;
70-
cdr.markForCheck();
80+
this.cdr.markForCheck();
7181
if (value === this.nzValue) {
72-
this.service.activated$.next(elementRef.nativeElement);
82+
this.service.activated$.next(this.elementRef.nativeElement);
7383
}
7484
}),
7585
switchMap(value =>
@@ -80,17 +90,12 @@ export class NzSegmentedItemComponent {
8090
)
8191
),
8292
filter(value => value === this.nzValue),
83-
takeUntilDestroyed()
93+
takeUntilDestroyed(this.destroyRef)
8494
)
8595
.subscribe(() => {
8696
this.isChecked = true;
87-
cdr.markForCheck();
97+
this.cdr.markForCheck();
8898
});
89-
90-
this.service.disabled$.pipe(takeUntilDestroyed()).subscribe(disabled => {
91-
this.nzDisabled = disabled;
92-
cdr.markForCheck();
93-
});
9499
}
95100

96101
handleClick(): void {

components/segmented/segmented.spec.ts

+40-1
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@
55

66
import { Component, DebugElement } from '@angular/core';
77
import { ComponentFixture, fakeAsync, TestBed, tick } from '@angular/core/testing';
8-
import { FormsModule } from '@angular/forms';
8+
import { FormControl, FormsModule, ReactiveFormsModule } from '@angular/forms';
99
import { By } from '@angular/platform-browser';
1010
import { provideNoopAnimations } from '@angular/platform-browser/animations';
1111

@@ -112,6 +112,36 @@ describe('nz-segmented', () => {
112112
expect(component.value).toBe('Daily');
113113
}));
114114
});
115+
describe('in reactive form', () => {
116+
let fixture: ComponentFixture<NzSegmentedInReactiveFormTestComponent>;
117+
let component: NzSegmentedInReactiveFormTestComponent;
118+
let segmentedComponent: DebugElement;
119+
120+
function getSegmentedOptionByIndex(index: number): HTMLElement {
121+
return segmentedComponent.nativeElement.querySelectorAll('.ant-segmented-item')[index];
122+
}
123+
124+
beforeEach(() => {
125+
TestBed.configureTestingModule({
126+
providers: [provideNoopAnimations()]
127+
});
128+
fixture = TestBed.createComponent(NzSegmentedInReactiveFormTestComponent);
129+
component = fixture.componentInstance;
130+
segmentedComponent = fixture.debugElement.query(By.directive(NzSegmentedComponent));
131+
fixture.detectChanges();
132+
});
133+
134+
it('first change form control value should work', fakeAsync(() => {
135+
expect(component.formControl.value).toBe('Weekly');
136+
const theThirdElement = getSegmentedOptionByIndex(2);
137+
dispatchMouseEvent(theThirdElement.querySelector('.ant-segmented-item-label')!, 'click');
138+
tick(400);
139+
fixture.detectChanges();
140+
const theSecondElement = getSegmentedOptionByIndex(1);
141+
expect(theSecondElement.classList.contains('ant-segmented-item-selected')).toBeFalse();
142+
expect(theThirdElement.classList.contains('ant-segmented-item-selected')).toBeTrue();
143+
}));
144+
});
115145
});
116146

117147
@Component({
@@ -138,3 +168,12 @@ export class NzSegmentedTestComponent {
138168
// empty
139169
}
140170
}
171+
172+
@Component({
173+
imports: [ReactiveFormsModule, NzSegmentedModule],
174+
template: `<nz-segmented [nzOptions]="options" [formControl]="formControl"></nz-segmented>`
175+
})
176+
export class NzSegmentedInReactiveFormTestComponent {
177+
options = ['Daily', 'Weekly', 'Monthly', 'Quarterly', 'Yearly'];
178+
formControl = new FormControl('Weekly');
179+
}

0 commit comments

Comments
 (0)