文章詳情頁(yè)
Angular組件庫(kù)ng-zorro-antd實(shí)現(xiàn)radio單選框選擇
瀏覽:377日期:2022-06-10 08:53:48
目錄
- antd組件庫(kù)升級(jí)之后代碼不生效
- 解決方法
- 總結(jié)
antd組件庫(kù)升級(jí)之后代碼不生效
項(xiàng)目業(yè)務(wù)之前的代碼設(shè)計(jì)了類(lèi)似radio單選框取消選擇的相關(guān)邏輯,用的是下面類(lèi)似的代碼實(shí)現(xiàn)的。但近期對(duì)ng-zorro-antd組件庫(kù)升級(jí)之后,下面的代碼不生效了。
import { Component } from "@angular/core";
@Component({
selector: "nz-demo-radio-radiogroup",
template: `
<nz-radio-group [(ngModel)]="radioValue">
<label nz-radio (click)="click("A")" nzValue="A">A</label>
<label nz-radio nzValue="B">B</label>
<label nz-radio nzValue="C">C</label>
<label nz-radio nzValue="D">D</label>
</nz-radio-group>
`
})
export class NzDemoRadioRadiogroupComponent {
radioValue = "A";
click(value: any) {
if (this.radioValue === value) {
this.radioValue = ""
}
}
}
于是我到組件庫(kù)源碼里去找原因,并寫(xiě)demo打斷點(diǎn)調(diào)試
- 將nz-radio-group綁定的radioValue值清空會(huì)首先走group組件下面的邏輯
writeValue(value: NzSafeAny): void {
this.value = value;
this.nzRadioService.select(value);
this.cdr.markForCheck();
}
- nz-radio 和 nz-radio-group都是共用這個(gè)NzRadioService,且組件內(nèi)init時(shí)都有對(duì)selected$這個(gè)流做監(jiān)聽(tīng)
@Injectable()
export class NzRadioService {
selected$ = new ReplaySubject<NzSafeAny>(1);
touched$ = new Subject<void>();
disabled$ = new ReplaySubject<boolean>(1);
name$ = new ReplaySubject<string>(1);
touch(): void {
this.touched$.next();
}
select(value: NzSafeAny): void {
this.selected$.next(value);
}
setDisabled(value: boolean): void {
this.disabled$.next(value);
}
setName(value: string): void {
this.name$.next(value);
}
}
// radio.component.ts ====> ngOnInit
this.nzRadioService.selected$.pipe(takeUntil(this.destroy$)).subscribe(value => {
const isChecked = this.isChecked;
this.isChecked = this.nzValue === value;
// We don"t have to run `onChange()` on each `nz-radio` button whenever the `selected$` emits.
// If we have 8 `nz-radio` buttons within the `nz-radio-group` and they"re all connected with
// `ngModel` or `formControl` then `onChange()` will be called 8 times for each `nz-radio` button.
// We prevent this by checking if `isChecked` has been changed or not.
if (
this.isNgModel &&
isChecked !== this.isChecked &&
// We"re only intereted if `isChecked` has been changed to `false` value to emit `false` to the ascendant form,
// since we already emit `true` within the `setupClickListener`.
this.isChecked === false
) {
this.onChange(false);
}
this.cdr.markForCheck();
});
- 當(dāng)監(jiān)聽(tīng)完值改變后,后面又執(zhí)行了radio的click事件,把點(diǎn)擊哪個(gè)radio的value值傳過(guò)去了,所以之前的清空值操作就被覆蓋了。
private setupClickListener(): void {
this.ngZone.runOutsideAngular(() => {
fromEvent<MouseEvent>(this.elementRef.nativeElement, "click")
.pipe(takeUntil(this.destroy$))
.subscribe(event => {
/** prevent label click triggered twice. **/
event.stopPropagation();
event.preventDefault();
if (this.nzDisabled || this.isChecked) {
return;
}
this.ngZone.run(() => {
// !!! again
this.nzRadioService?.select(this.nzValue);
if (this.isNgModel) {
this.isChecked = true;
this.onChange(true);
}
this.cdr.markForCheck();
});
});
});
}
解決方法
清空值的操作加setTimeout 使組件庫(kù)內(nèi)部先執(zhí)行完click后續(xù)再執(zhí)行。
import { Component } from "@angular/core";
@Component({
selector: "nz-demo-radio-radiogroup",
template: `
<nz-radio-group [(ngModel)]="radioValue">
<label nz-radio (click)="click("A")" nzValue="A">A</label>
<label nz-radio nzValue="B">B</label>
<label nz-radio nzValue="C">C</label>
<label nz-radio nzValue="D">D</label>
</nz-radio-group>
`
})
export class NzDemoRadioRadiogroupComponent {
radioValue = "A";
click(value: any) {
if (this.radioValue === value) {
setTimeout(()=>{
this.radioValue = ""
})
}
}
}
總結(jié)
其實(shí)組件庫(kù)單選radio本身是不支持取消選擇的,正解應(yīng)該是用checkbox實(shí)現(xiàn)相關(guān)的業(yè)務(wù)邏輯才對(duì),但很久之前的業(yè)務(wù)邏輯涉及到很多地方的修改,此時(shí)再換checkbox并且換樣式的話,改動(dòng)的還是比較大的,就先簡(jiǎn)單解決這個(gè)問(wèn)題。
標(biāo)簽:
JavaScript
排行榜

網(wǎng)公網(wǎng)安備