Commit c6295556c1744d3f860c3f85465024b20de01165
1 parent
4e5f4851
UI: Improvement autocomplete component: debounceTime and catchError
Showing
9 changed files
with
85 additions
and
33 deletions
... | ... | @@ -16,9 +16,9 @@ |
16 | 16 | |
17 | 17 | import { AfterViewInit, Component, ElementRef, forwardRef, Input, OnInit, ViewChild } from '@angular/core'; |
18 | 18 | import { ControlValueAccessor, FormBuilder, FormGroup, NG_VALUE_ACCESSOR } from '@angular/forms'; |
19 | -import { Observable } from 'rxjs'; | |
20 | -import { map, mergeMap, startWith, tap } from 'rxjs/operators'; | |
21 | -import { PageData } from '@shared/models/page/page-data'; | |
19 | +import { Observable, of } from 'rxjs'; | |
20 | +import { catchError, debounceTime, distinctUntilChanged, map, startWith, switchMap, tap } from 'rxjs/operators'; | |
21 | +import { emptyPageData, PageData } from '@shared/models/page/page-data'; | |
22 | 22 | import { Store } from '@ngrx/store'; |
23 | 23 | import { AppState } from '@app/core/core.state'; |
24 | 24 | import { TranslateService } from '@ngx-translate/core'; |
... | ... | @@ -88,6 +88,7 @@ export class AliasesEntityAutocompleteComponent implements ControlValueAccessor, |
88 | 88 | ngOnInit() { |
89 | 89 | this.filteredEntityInfos = this.selectEntityInfoFormGroup.get('entityInfo').valueChanges |
90 | 90 | .pipe( |
91 | + debounceTime(150), | |
91 | 92 | tap(value => { |
92 | 93 | let modelValue; |
93 | 94 | if (typeof value === 'string' || !value) { |
... | ... | @@ -99,7 +100,8 @@ export class AliasesEntityAutocompleteComponent implements ControlValueAccessor, |
99 | 100 | }), |
100 | 101 | startWith<string | EntityInfo>(''), |
101 | 102 | map(value => value ? (typeof value === 'string' ? value : value.name) : ''), |
102 | - mergeMap(name => this.fetchEntityInfos(name) ) | |
103 | + distinctUntilChanged(), | |
104 | + switchMap(name => this.fetchEntityInfos(name)) | |
103 | 105 | ); |
104 | 106 | } |
105 | 107 | |
... | ... | @@ -142,7 +144,9 @@ export class AliasesEntityAutocompleteComponent implements ControlValueAccessor, |
142 | 144 | } |
143 | 145 | |
144 | 146 | getEntityInfos(searchText: string): Observable<PageData<EntityInfo>> { |
145 | - return this.entityService.findEntityInfosByFilterAndName(this.entityFilter, searchText, {ignoreLoading: true}); | |
147 | + return this.entityService.findEntityInfosByFilterAndName(this.entityFilter, searchText, {ignoreLoading: true}).pipe( | |
148 | + catchError(() => of(emptyPageData<EntityInfo>())) | |
149 | + ); | |
146 | 150 | } |
147 | 151 | |
148 | 152 | clear() { | ... | ... |
... | ... | @@ -20,16 +20,18 @@ import { |
20 | 20 | EventEmitter, |
21 | 21 | forwardRef, |
22 | 22 | Input, |
23 | - NgZone, OnChanges, | |
23 | + NgZone, | |
24 | + OnChanges, | |
24 | 25 | OnInit, |
25 | - Output, SimpleChanges, | |
26 | + Output, | |
27 | + SimpleChanges, | |
26 | 28 | ViewChild |
27 | 29 | } from '@angular/core'; |
28 | 30 | import { ControlValueAccessor, FormBuilder, FormGroup, NG_VALUE_ACCESSOR } from '@angular/forms'; |
29 | -import { Observable } from 'rxjs'; | |
31 | +import { Observable, of } from 'rxjs'; | |
30 | 32 | import { PageLink } from '@shared/models/page/page-link'; |
31 | 33 | import { Direction } from '@shared/models/page/sort-order'; |
32 | -import { map, mergeMap, share, tap } from 'rxjs/operators'; | |
34 | +import { catchError, debounceTime, distinctUntilChanged, map, share, switchMap, tap } from 'rxjs/operators'; | |
33 | 35 | import { Store } from '@ngrx/store'; |
34 | 36 | import { AppState } from '@app/core/core.state'; |
35 | 37 | import { TranslateService } from '@ngx-translate/core'; |
... | ... | @@ -44,6 +46,7 @@ import { DeviceProfileService } from '@core/http/device-profile.service'; |
44 | 46 | import { DeviceProfileDialogComponent, DeviceProfileDialogData } from './device-profile-dialog.component'; |
45 | 47 | import { MatAutocomplete } from '@angular/material/autocomplete'; |
46 | 48 | import { AddDeviceProfileDialogComponent, AddDeviceProfileDialogData } from './add-device-profile-dialog.component'; |
49 | +import { emptyPageData } from "@shared/models/page/page-data"; | |
47 | 50 | |
48 | 51 | @Component({ |
49 | 52 | selector: 'tb-device-profile-autocomplete', |
... | ... | @@ -143,6 +146,7 @@ export class DeviceProfileAutocompleteComponent implements ControlValueAccessor, |
143 | 146 | ngOnInit() { |
144 | 147 | this.filteredDeviceProfiles = this.selectDeviceProfileFormGroup.get('deviceProfile').valueChanges |
145 | 148 | .pipe( |
149 | + debounceTime(150), | |
146 | 150 | tap((value: DeviceProfileInfo | string) => { |
147 | 151 | let modelValue: DeviceProfileInfo | null; |
148 | 152 | if (typeof value === 'string' || !value) { |
... | ... | @@ -169,7 +173,8 @@ export class DeviceProfileAutocompleteComponent implements ControlValueAccessor, |
169 | 173 | return ''; |
170 | 174 | } |
171 | 175 | }), |
172 | - mergeMap(name => this.fetchDeviceProfiles(name) ), | |
176 | + distinctUntilChanged(), | |
177 | + switchMap(name => this.fetchDeviceProfiles(name)), | |
173 | 178 | share() |
174 | 179 | ); |
175 | 180 | } |
... | ... | @@ -289,6 +294,7 @@ export class DeviceProfileAutocompleteComponent implements ControlValueAccessor, |
289 | 294 | direction: Direction.ASC |
290 | 295 | }); |
291 | 296 | return this.deviceProfileService.getDeviceProfileInfos(pageLink, this.transportType, {ignoreLoading: true}).pipe( |
297 | + catchError(() => of(emptyPageData<DeviceProfileInfo>())), | |
292 | 298 | map(pageData => { |
293 | 299 | let data = pageData.data; |
294 | 300 | if (this.displayAllOnEmpty) { | ... | ... |
... | ... | @@ -16,10 +16,10 @@ |
16 | 16 | |
17 | 17 | import { Component, ElementRef, EventEmitter, forwardRef, Input, OnInit, Output, ViewChild } from '@angular/core'; |
18 | 18 | import { ControlValueAccessor, FormBuilder, FormGroup, NG_VALUE_ACCESSOR } from '@angular/forms'; |
19 | -import { Observable } from 'rxjs'; | |
19 | +import { Observable, of } from 'rxjs'; | |
20 | 20 | import { PageLink } from '@shared/models/page/page-link'; |
21 | 21 | import { Direction } from '@shared/models/page/sort-order'; |
22 | -import { map, mergeMap, share, startWith, tap } from 'rxjs/operators'; | |
22 | +import { catchError, debounceTime, distinctUntilChanged, map, share, switchMap, tap } from 'rxjs/operators'; | |
23 | 23 | import { Store } from '@ngrx/store'; |
24 | 24 | import { AppState } from '@app/core/core.state'; |
25 | 25 | import { TranslateService } from '@ngx-translate/core'; |
... | ... | @@ -33,6 +33,7 @@ import { ENTER } from '@angular/cdk/keycodes'; |
33 | 33 | import { TenantProfile } from '@shared/models/tenant.model'; |
34 | 34 | import { MatDialog } from '@angular/material/dialog'; |
35 | 35 | import { TenantProfileDialogComponent, TenantProfileDialogData } from './tenant-profile-dialog.component'; |
36 | +import { emptyPageData } from "@shared/models/page/page-data"; | |
36 | 37 | |
37 | 38 | @Component({ |
38 | 39 | selector: 'tb-tenant-profile-autocomplete', |
... | ... | @@ -99,6 +100,7 @@ export class TenantProfileAutocompleteComponent implements ControlValueAccessor, |
99 | 100 | ngOnInit() { |
100 | 101 | this.filteredTenantProfiles = this.selectTenantProfileFormGroup.get('tenantProfile').valueChanges |
101 | 102 | .pipe( |
103 | + debounceTime(150), | |
102 | 104 | tap((value: EntityInfoData | string) => { |
103 | 105 | let modelValue: TenantProfileId | null; |
104 | 106 | if (typeof value === 'string' || !value) { |
... | ... | @@ -109,7 +111,8 @@ export class TenantProfileAutocompleteComponent implements ControlValueAccessor, |
109 | 111 | this.updateView(modelValue); |
110 | 112 | }), |
111 | 113 | map(value => value ? (typeof value === 'string' ? value : value.name) : ''), |
112 | - mergeMap(name => this.fetchTenantProfiles(name) ), | |
114 | + distinctUntilChanged(), | |
115 | + switchMap(name => this.fetchTenantProfiles(name)), | |
113 | 116 | share() |
114 | 117 | ); |
115 | 118 | } |
... | ... | @@ -174,6 +177,7 @@ export class TenantProfileAutocompleteComponent implements ControlValueAccessor, |
174 | 177 | direction: Direction.ASC |
175 | 178 | }); |
176 | 179 | return this.tenantProfileService.getTenantProfileInfos(pageLink, {ignoreLoading: true}).pipe( |
180 | + catchError(() => of(emptyPageData<EntityInfoData>())), | |
177 | 181 | map(pageData => { |
178 | 182 | return pageData.data; |
179 | 183 | }) | ... | ... |
... | ... | @@ -16,8 +16,8 @@ |
16 | 16 | |
17 | 17 | import { Component, ElementRef, forwardRef, Input, OnInit, ViewChild } from '@angular/core'; |
18 | 18 | import { ControlValueAccessor, FormBuilder, FormGroup, NG_VALUE_ACCESSOR } from '@angular/forms'; |
19 | -import { Observable } from 'rxjs'; | |
20 | -import { map, mergeMap, share, tap } from 'rxjs/operators'; | |
19 | +import { Observable, of } from 'rxjs'; | |
20 | +import { catchError, debounceTime, distinctUntilChanged, map, share, switchMap, tap } from 'rxjs/operators'; | |
21 | 21 | import { Store } from '@ngrx/store'; |
22 | 22 | import { AppState } from '@core/core.state'; |
23 | 23 | import { TranslateService } from '@ngx-translate/core'; |
... | ... | @@ -99,6 +99,7 @@ export class RuleChainAutocompleteComponent implements ControlValueAccessor, OnI |
99 | 99 | ngOnInit() { |
100 | 100 | this.filteredRuleChains = this.selectRuleChainFormGroup.get('ruleChainId').valueChanges |
101 | 101 | .pipe( |
102 | + debounceTime(150), | |
102 | 103 | tap(value => { |
103 | 104 | let modelValue; |
104 | 105 | if (typeof value === 'string' || !value) { |
... | ... | @@ -110,8 +111,10 @@ export class RuleChainAutocompleteComponent implements ControlValueAccessor, OnI |
110 | 111 | if (value === null) { |
111 | 112 | this.clear(); |
112 | 113 | } |
113 | - }), map(value => value ? (typeof value === 'string' ? value : value.name) : ''), | |
114 | - mergeMap(name => this.fetchRuleChain(name) ), | |
114 | + }), | |
115 | + map(value => value ? (typeof value === 'string' ? value : value.name) : ''), | |
116 | + distinctUntilChanged(), | |
117 | + switchMap(name => this.fetchRuleChain(name) ), | |
115 | 118 | share() |
116 | 119 | ); |
117 | 120 | } |
... | ... | @@ -190,7 +193,9 @@ export class RuleChainAutocompleteComponent implements ControlValueAccessor, OnI |
190 | 193 | this.searchText = searchText; |
191 | 194 | // voba: at the moment device profiles are not supported by edge, so 'core' hardcoded |
192 | 195 | return this.entityService.getEntitiesByNameFilter(EntityType.RULE_CHAIN, searchText, |
193 | - 50, RuleChainType.CORE, {ignoreLoading: true}); | |
196 | + 50, RuleChainType.CORE, {ignoreLoading: true}).pipe( | |
197 | + catchError(() => of([])) | |
198 | + ); | |
194 | 199 | } |
195 | 200 | |
196 | 201 | clear() { | ... | ... |
... | ... | @@ -19,7 +19,7 @@ import { ControlValueAccessor, FormBuilder, FormGroup, NG_VALUE_ACCESSOR } from |
19 | 19 | import { Observable, of } from 'rxjs'; |
20 | 20 | import { PageLink } from '@shared/models/page/page-link'; |
21 | 21 | import { Direction } from '@shared/models/page/sort-order'; |
22 | -import { map, mergeMap, startWith, tap } from 'rxjs/operators'; | |
22 | +import { catchError, debounceTime, distinctUntilChanged, map, startWith, switchMap, tap } from 'rxjs/operators'; | |
23 | 23 | import { emptyPageData, PageData } from '@shared/models/page/page-data'; |
24 | 24 | import { DashboardInfo } from '@app/shared/models/dashboard.models'; |
25 | 25 | import { DashboardService } from '@core/http/dashboard.service'; |
... | ... | @@ -107,6 +107,7 @@ export class DashboardAutocompleteComponent implements ControlValueAccessor, OnI |
107 | 107 | ngOnInit() { |
108 | 108 | this.filteredDashboards = this.selectDashboardFormGroup.get('dashboard').valueChanges |
109 | 109 | .pipe( |
110 | + debounceTime(150), | |
110 | 111 | tap(value => { |
111 | 112 | let modelValue; |
112 | 113 | if (typeof value === 'string' || !value) { |
... | ... | @@ -118,7 +119,8 @@ export class DashboardAutocompleteComponent implements ControlValueAccessor, OnI |
118 | 119 | }), |
119 | 120 | startWith<string | DashboardInfo>(''), |
120 | 121 | map(value => value ? (typeof value === 'string' ? value : value.name) : ''), |
121 | - mergeMap(name => this.fetchDashboards(name) ) | |
122 | + distinctUntilChanged(), | |
123 | + switchMap(name => this.fetchDashboards(name) ) | |
122 | 124 | ); |
123 | 125 | } |
124 | 126 | |
... | ... | @@ -189,6 +191,7 @@ export class DashboardAutocompleteComponent implements ControlValueAccessor, OnI |
189 | 191 | direction: Direction.ASC |
190 | 192 | }); |
191 | 193 | return this.getDashboards(pageLink).pipe( |
194 | + catchError(() => of(emptyPageData<DashboardInfo>())), | |
192 | 195 | map(pageData => { |
193 | 196 | return pageData.data; |
194 | 197 | }) | ... | ... |
... | ... | @@ -26,8 +26,8 @@ import { |
26 | 26 | ViewChild |
27 | 27 | } from '@angular/core'; |
28 | 28 | import { ControlValueAccessor, FormBuilder, FormGroup, NG_VALUE_ACCESSOR } from '@angular/forms'; |
29 | -import { Observable } from 'rxjs'; | |
30 | -import { map, mergeMap, share, tap } from 'rxjs/operators'; | |
29 | +import { Observable, of } from 'rxjs'; | |
30 | +import { catchError, debounceTime, distinctUntilChanged, map, share, switchMap, tap } from 'rxjs/operators'; | |
31 | 31 | import { Store } from '@ngrx/store'; |
32 | 32 | import { AppState } from '@app/core/core.state'; |
33 | 33 | import { TranslateService } from '@ngx-translate/core'; |
... | ... | @@ -142,6 +142,7 @@ export class EntityAutocompleteComponent implements ControlValueAccessor, OnInit |
142 | 142 | ngOnInit() { |
143 | 143 | this.filteredEntities = this.selectEntityFormGroup.get('entity').valueChanges |
144 | 144 | .pipe( |
145 | + debounceTime(150), | |
145 | 146 | tap(value => { |
146 | 147 | let modelValue; |
147 | 148 | if (typeof value === 'string' || !value) { |
... | ... | @@ -156,7 +157,8 @@ export class EntityAutocompleteComponent implements ControlValueAccessor, OnInit |
156 | 157 | }), |
157 | 158 | // startWith<string | BaseData<EntityId>>(''), |
158 | 159 | map(value => value ? (typeof value === 'string' ? value : value.name) : ''), |
159 | - mergeMap(name => this.fetchEntities(name) ), | |
160 | + distinctUntilChanged(), | |
161 | + switchMap(name => this.fetchEntities(name)), | |
160 | 162 | share() |
161 | 163 | ); |
162 | 164 | } |
... | ... | @@ -326,6 +328,7 @@ export class EntityAutocompleteComponent implements ControlValueAccessor, OnInit |
326 | 328 | const targetEntityType = this.checkEntityType(this.entityTypeValue); |
327 | 329 | return this.entityService.getEntitiesByNameFilter(targetEntityType, searchText, |
328 | 330 | 50, this.entitySubtypeValue, {ignoreLoading: true}).pipe( |
331 | + catchError(() => of(null)), | |
329 | 332 | map((data) => { |
330 | 333 | if (data) { |
331 | 334 | if (this.excludeEntityIds && this.excludeEntityIds.length) { | ... | ... |
... | ... | @@ -16,8 +16,17 @@ |
16 | 16 | |
17 | 17 | import { AfterViewInit, Component, ElementRef, forwardRef, Input, OnDestroy, OnInit, ViewChild } from '@angular/core'; |
18 | 18 | import { ControlValueAccessor, FormBuilder, FormGroup, NG_VALUE_ACCESSOR } from '@angular/forms'; |
19 | -import { Observable, Subscription, throwError } from 'rxjs'; | |
20 | -import { map, mergeMap, publishReplay, refCount, tap } from 'rxjs/operators'; | |
19 | +import { Observable, of, Subscription, throwError } from 'rxjs'; | |
20 | +import { | |
21 | + catchError, | |
22 | + debounceTime, | |
23 | + distinctUntilChanged, | |
24 | + map, | |
25 | + publishReplay, | |
26 | + refCount, | |
27 | + switchMap, | |
28 | + tap | |
29 | +} from 'rxjs/operators'; | |
21 | 30 | import { Store } from '@ngrx/store'; |
22 | 31 | import { AppState } from '@app/core/core.state'; |
23 | 32 | import { TranslateService } from '@ngx-translate/core'; |
... | ... | @@ -137,12 +146,14 @@ export class EntitySubTypeAutocompleteComponent implements ControlValueAccessor, |
137 | 146 | |
138 | 147 | this.filteredSubTypes = this.subTypeFormGroup.get('subType').valueChanges |
139 | 148 | .pipe( |
149 | + debounceTime(150), | |
150 | + distinctUntilChanged(), | |
140 | 151 | tap(value => { |
141 | 152 | this.updateView(value); |
142 | 153 | }), |
143 | 154 | // startWith<string | EntitySubtype>(''), |
144 | 155 | map(value => value ? value : ''), |
145 | - mergeMap(type => this.fetchSubTypes(type) ) | |
156 | + switchMap(type => this.fetchSubTypes(type)) | |
146 | 157 | ); |
147 | 158 | } |
148 | 159 | |
... | ... | @@ -221,6 +232,7 @@ export class EntitySubTypeAutocompleteComponent implements ControlValueAccessor, |
221 | 232 | } |
222 | 233 | if (subTypesObservable) { |
223 | 234 | this.subTypes = subTypesObservable.pipe( |
235 | + catchError(() => of([] as Array<EntitySubtype>)), | |
224 | 236 | map(subTypes => subTypes.map(subType => subType.type)), |
225 | 237 | publishReplay(1), |
226 | 238 | refCount() | ... | ... |
... | ... | @@ -16,8 +16,8 @@ |
16 | 16 | |
17 | 17 | import { Component, ElementRef, forwardRef, Input, OnInit, ViewChild } from '@angular/core'; |
18 | 18 | import { ControlValueAccessor, FormBuilder, FormGroup, NG_VALUE_ACCESSOR } from '@angular/forms'; |
19 | -import { Observable } from 'rxjs'; | |
20 | -import { map, mergeMap, share, tap } from 'rxjs/operators'; | |
19 | +import { Observable, of } from 'rxjs'; | |
20 | +import { catchError, debounceTime, distinctUntilChanged, map, share, switchMap, tap } from 'rxjs/operators'; | |
21 | 21 | import { Store } from '@ngrx/store'; |
22 | 22 | import { AppState } from '@core/core.state'; |
23 | 23 | import { TranslateService } from '@ngx-translate/core'; |
... | ... | @@ -27,11 +27,11 @@ import { EntityType } from '@shared/models/entity-type.models'; |
27 | 27 | import { BaseData } from '@shared/models/base-data'; |
28 | 28 | import { EntityService } from '@core/http/entity.service'; |
29 | 29 | import { TruncatePipe } from '@shared/pipe/truncate.pipe'; |
30 | -import { MatAutocompleteTrigger } from '@angular/material/autocomplete'; | |
31 | 30 | import { OtaPackageInfo, OtaUpdateTranslation, OtaUpdateType } from '@shared/models/ota-package.models'; |
32 | 31 | import { OtaPackageService } from '@core/http/ota-package.service'; |
33 | 32 | import { PageLink } from '@shared/models/page/page-link'; |
34 | 33 | import { Direction } from '@shared/models/page/sort-order'; |
34 | +import { emptyPageData } from "@shared/models/page/page-data"; | |
35 | 35 | |
36 | 36 | @Component({ |
37 | 37 | selector: 'tb-ota-package-autocomplete', |
... | ... | @@ -109,6 +109,7 @@ export class OtaPackageAutocompleteComponent implements ControlValueAccessor, On |
109 | 109 | ngOnInit() { |
110 | 110 | this.filteredPackages = this.otaPackageFormGroup.get('packageId').valueChanges |
111 | 111 | .pipe( |
112 | + debounceTime(150), | |
112 | 113 | tap(value => { |
113 | 114 | let modelValue; |
114 | 115 | if (typeof value === 'string' || !value) { |
... | ... | @@ -122,7 +123,8 @@ export class OtaPackageAutocompleteComponent implements ControlValueAccessor, On |
122 | 123 | } |
123 | 124 | }), |
124 | 125 | map(value => value ? (typeof value === 'string' ? value : value.title) : ''), |
125 | - mergeMap(name => this.fetchPackages(name)), | |
126 | + distinctUntilChanged(), | |
127 | + switchMap(name => this.fetchPackages(name)), | |
126 | 128 | share() |
127 | 129 | ); |
128 | 130 | } |
... | ... | @@ -217,6 +219,7 @@ export class OtaPackageAutocompleteComponent implements ControlValueAccessor, On |
217 | 219 | }); |
218 | 220 | return this.otaPackageService.getOtaPackagesInfoByDeviceProfileId(pageLink, this.deviceProfileId, this.type, |
219 | 221 | {ignoreLoading: true}).pipe( |
222 | + catchError(() => of(emptyPageData<OtaPackageInfo>())), | |
220 | 223 | map((data) => data && data.data.length ? data.data : null) |
221 | 224 | ); |
222 | 225 | } | ... | ... |
... | ... | @@ -16,8 +16,17 @@ |
16 | 16 | |
17 | 17 | import { AfterViewInit, Component, ElementRef, forwardRef, Input, OnDestroy, OnInit, ViewChild } from '@angular/core'; |
18 | 18 | import { ControlValueAccessor, FormBuilder, FormGroup, NG_VALUE_ACCESSOR } from '@angular/forms'; |
19 | -import { Observable } from 'rxjs'; | |
20 | -import { map, mergeMap, publishReplay, refCount, tap } from 'rxjs/operators'; | |
19 | +import { Observable, of } from 'rxjs'; | |
20 | +import { | |
21 | + catchError, | |
22 | + debounceTime, | |
23 | + distinctUntilChanged, | |
24 | + map, | |
25 | + publishReplay, | |
26 | + refCount, | |
27 | + switchMap, | |
28 | + tap | |
29 | +} from 'rxjs/operators'; | |
21 | 30 | import { Store } from '@ngrx/store'; |
22 | 31 | import { AppState } from '@app/core/core.state'; |
23 | 32 | import { TranslateService } from '@ngx-translate/core'; |
... | ... | @@ -87,11 +96,13 @@ export class QueueTypeListComponent implements ControlValueAccessor, OnInit, Aft |
87 | 96 | ngOnInit() { |
88 | 97 | this.filteredQueues = this.queueFormGroup.get('queue').valueChanges |
89 | 98 | .pipe( |
99 | + debounceTime(150), | |
100 | + distinctUntilChanged(), | |
90 | 101 | tap(value => { |
91 | 102 | this.updateView(value); |
92 | 103 | }), |
93 | 104 | map(value => value ? value : ''), |
94 | - mergeMap(queue => this.fetchQueues(queue) ) | |
105 | + switchMap(queue => this.fetchQueues(queue) ) | |
95 | 106 | ); |
96 | 107 | } |
97 | 108 | |
... | ... | @@ -138,6 +149,7 @@ export class QueueTypeListComponent implements ControlValueAccessor, OnInit, Aft |
138 | 149 | fetchQueues(searchText?: string): Observable<Array<string>> { |
139 | 150 | this.searchText = searchText; |
140 | 151 | return this.getQueues().pipe( |
152 | + catchError(() => of([])), | |
141 | 153 | map(queues => { |
142 | 154 | const result = queues.filter( queue => { |
143 | 155 | return searchText ? queue.toUpperCase().startsWith(searchText.toUpperCase()) : true; | ... | ... |