Tengo un menú desplegable que obtiene valores de un servicio.
Desplegable
<mat-select *ngIf="selectedCloudTypeName === 'AWS'" class="select--width--130" [formControl]="awsOwnersControl" placeholder="AWS Owners" msInfiniteScroll (infiniteScroll)="loadMoreAwsOwners()" [complete]="currentAwsOwnerssDropdownOffset >= awsOwnersTotalCount" > <mat-option *ngFor="let owner of awsOwners$ | async" [value]="owner.id"> {{ owner.name }} </mat-option> </mat-select>Llamada de servicio en archivo TS
getAwsOwners(offset = 0) { this.isLoading$.next(true); this.awsService .getOwnersListForAws(this.selectedCredentialIdForCloudType, this.selectedPlatform, { offset, limit: 100 }) .subscribe( (owners: PaginatedResult<CommonEnumValue[]>) => { this.awsOwners.next(owners.data); this.awsOwnersTotalCount = owners.totalCount; this.isLoading$.next(false); }, (error) => { this.isLoading$.next(false); this.alertify.error(error); }, );}
En OnInit hook uso un Observable
this.awsOwners$ = this.awsOwners.asObservable().pipe(scan((acc, curr) => [...acc, ...curr], []));que declaro en propiedad en el expediente como
awsOwners = new BehaviorSubject<CommonEnumValue[]>([]); awsOwners$: Observable<CommonEnumValue[]>;El problema es que cuando llamo a la función getAwsOnwers con un valor de 'plataforma seleccionada' diferente, los datos antiguos persisten y los datos nuevos se agregan.
Traté de borrar el Asunto awsOwners así
this.awsOwners.next([]);antes de que lo llame, pero lo borra y se agregan nuevos datos al anterior,
¿Alguna forma de cómo puedo borrarlo?
Siento que en el operador de escaneo de alguna manera necesito borrar el '.acc' porque acumula los valores.
scan de esta canalización.awsOwners this.awsOwners$ this.awsOwners$ = this.awsOwners.asObservable()this.selectedPlatform como Asunto, y haga que llame a getAwsOwners si cambia this._selectedPlatform$ = new Subject() get selectedPlatform$() { // if platform is object you should provide comparing callback to distinctUntilChanged operator return this._selectedPlatform$.asObservable.pipe(distinctUntilChanged(), tap(() => //make getAwsOwners() accept platform as an parameter and offset as a optional one. this.getAwsOwners(platform); )) }getAwsOwners , haga algunos cambios .subscribe( (owners: PaginatedResult<CommonEnumValue[]>) => { // always if offset === 0 you should reset owners state this.awsOwners.next(offset ? [...this.awsOwners.getValue(), ...owners.data] : owners.data ); this.awsOwnersTotalCount = owners.totalCount; this.isLoading$.next(false); }, (error) => { this.isLoading$.next(false); this.alertify.error(error); }, );podría restablecer su escaneo si su valor curr en el escaneo lambda está vacío.
(acc, curr) => curr === [] ? [] : [...acc, ...curr]pero eso me parecería un poco sucio.
puede crear un BehaviourSubject y emitir cada vez que desee restablecer su valor. entonces podría canalizar su sujeto y cambiarMap a su escaneo observable. de esta manera, el observable siempre se volvería a suscribir a su escaneado observable y, por lo tanto, comenzaría de nuevo, ya que switchMap se da de baja y se suscribe automáticamente si la fuente emite un valor.
podría verse algo como esto:
BehaviourSubject resetSubject$ = new BehaviourSubject<void>(); // use behaviour subject to get an initial emit awsOwners$ = resetSubject$.pipe( switchMap(() => this.awsOwners.asObservable().pipe( scan((acc, curr) => [...acc, ...curr], []) ), ); // call this to reset your scan resetSubject$.emit()En lugar de tener un método que actualice un tema, simplemente cree una secuencia que mantenga el estado de los datos de la lista, si se está cargando, y el desplazamiento de la página actual.
readonly offsetChangeSubject = new Subject<number>(); readonly selectedPlatformSubject = new Subject<string>(); readonly ownersList$ = this.selectedPlatformSubject.pipe( switchMap(platform) => offsetChangeSubject.pipe( startWith(0), mergeScan((acc, offset) => this.awsService.getOwnersListForAws(this.credentialId, platform, { offset, limit: 100 }).pipe( startWith({ ...acc, isLoading: true, offset }) map(page => ({ isLoading: false, offset, owners: owners.concat(page.data), totalCount: page.totalCount })) ), { isLoading: false, owners: [], totalCount: 0, offset } ) )) )notas
Si no es evidente, siempre habrá un resultado una vez que platformSubject emita por primera vez.
Supuse que una vez que esa plataforma cambiara, también querrías restablecer el desplazamiento, esa es una de las razones por las que no hice de offsetSubject un BehaviorSubject y en su lugar usé startWith para emitir 0. Entonces recuperarías el valor actual de el desplazamiento de la lista de propietarios $ observable, no el offsetChangeSubject, eso es solo para actualizaciones.
Puede usar shareReplay si desea que el estado de la lista actual sea algo más que la vista.