Angular組件庫ng-zorro-antd實(shí)現(xiàn)radio單選框選擇
antd組件庫升級(jí)之后代碼不生效
項(xiàng)目業(yè)務(wù)之前的代碼設(shè)計(jì)了類似radio單選框取消選擇的相關(guān)邏輯,用的是下面類似的代碼實(shí)現(xiàn)的。但近期對(duì)ng-zorro-antd組件庫升級(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 = '' } } }
于是我到組件庫源碼里去找原因,并寫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)聽
@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)聽完值改變后,后面又執(zhí)行了radio的click事件,把點(diǎn)擊哪個(gè)radio的value值傳過去了,所以之前的清空值操作就被覆蓋了。
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 使組件庫內(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í)組件庫單選radio本身是不支持取消選擇的,正解應(yīng)該是用checkbox實(shí)現(xiàn)相關(guān)的業(yè)務(wù)邏輯才對(duì),但很久之前的業(yè)務(wù)邏輯涉及到很多地方的修改,此時(shí)再換checkbox并且換樣式的話,改動(dòng)的還是比較大的,就先簡單解決這個(gè)問題。
相關(guān)文章
Angular2.0/4.0 使用Echarts圖表的示例代碼
本篇文章主要介紹了Angular2.0/4.0 使用Echarts的示例代碼,小編覺得挺不錯(cuò)的,現(xiàn)在分享給大家,也給大家做個(gè)參考。一起跟隨小編過來看看吧2017-12-12AngularJS內(nèi)建服務(wù)$location及其功能詳解
這篇文章主要為大家詳細(xì)介紹了AngularJS內(nèi)建服務(wù)$location及$location功能,感興趣的小伙伴們可以參考一下2016-07-07Angular2生命周期鉤子函數(shù)的詳細(xì)介紹
這篇文章主要介紹了Angular2生命周期鉤子函數(shù)的詳細(xì)介紹,Angular提供組件生命周期鉤子,可以讓我們更好的開發(fā)Angular應(yīng)用,有興趣的可以了解一下2017-07-07在 Angular2 中實(shí)現(xiàn)自定義校驗(yàn)指令(確認(rèn)密碼)的方法
這篇文章給大家探索 Angular 2 內(nèi)建的自定義驗(yàn)證,非常不錯(cuò),具有參考借鑒價(jià)值,需要的朋友參考下2017-01-01解決angular的post請(qǐng)求后SpringMVC后臺(tái)接收不到參數(shù)值問題的方法
這篇文章主要介紹了解決angular的post請(qǐng)求后SpringMVC后臺(tái)接收不到參數(shù)值問題的方法,感興趣的小伙伴們可以參考一下2015-12-12angularJs中$http獲取后臺(tái)數(shù)據(jù)的實(shí)例講解
今天小編就為大家分享一篇angularJs中$http獲取后臺(tái)數(shù)據(jù)的實(shí)例講解,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。一起跟隨小編過來看看吧2018-08-08