1

我在我的 HTML 中使用了这些 observables,但是每次我的 HTML 控件的输入值发生变化时它们都不会重新发出(并且它们依赖于这些值,因此它们变得不同步)。例如,当这个更新 ( [(ngModel)]="mappedItem.selectedBusinessEntities") 然后selectedBusinessEntitiesOptionsAsDtos$ | async需要重新发出。请参见第二个 HTML 控件的选项是第一个 HTML 控件的选定选项。我是否需要以[(ngModel)]="mappedItem.selectedBusinessEntities"某种方式使该值成为可观察的?

HTML:

<cb-selection-list name="selectedBusinessEntities"
                   [(ngModel)]="mappedItem.selectedBusinessEntities"
                   [options]="businessEntitiesOptions$ | async"
                   [readonly]="isView()"
                   maxHeight="400px"
                   [slim]="true">
</cb-selection-list>
<cb-select label="Primary Business Entity"
           name="primaryBusinessEntity"
           [required]="true"
           [(ngModel)]="mappedItem.primaryBusinessEntity"
           [options]="selectedBusinessEntitiesOptionsAsDtos$ | async"
           [readonly]="isView()">
</cb-select>

打字稿:

@Component({
    selector: 'cb-user-details',
    templateUrl: './user-details.component.html',
    styleUrls: ['./user-details.component.scss']
})
export class UserDetailsComponent implements OnInit {

    public teamsOptions$: Observable<ITeamDto[]>;
    public userRoleTagsOptions$: Observable<ITagDto[]>;
    public userRoleTagsOptions: ITagDto[];
    public businessEntitiesOptions$: Observable<IBusinessEntityDto[]>;
    public isMobileNumberMandatory$: Observable<boolean>;
    public selectedBusinessEntitiesOptionsAsDtos$: Observable<IBusinessEntityDto[]>;

public ngOnInit(): void {
    this._initSelectOptions();
}
    
private _initSelectOptions(): void {
    this.teamsOptions$ = this.teamsLogicService.$getList();
    this.userRoleTagsOptions$ = this.tagsLogicService.$getList();
    this.businessEntitiesOptions$ = this.businessEntitiesLogicService
        .$getList()
        .pipe(
            map(businessEntities => {
                return orderBy(businessEntities, businessEntity => businessEntity?.name?.toLowerCase());
            })
        );
    this.selectedBusinessEntitiesOptionsAsDtos$ = this.businessEntitiesOptions$.pipe(
        map(businessEntities => {
            return businessEntities
                .filter(businessEntity => includes(
                    this.mappedItem.selectedBusinessEntities, businessEntity.id)
                );
        }));
    this.isMobileNumberMandatory$ = this.selectedBusinessEntitiesOptionsAsDtos$.pipe(
        map(businessEntities => {
            const buildingConsultantTag = this.userRoleTagsOptions?.find(
                tag => tag.key === USER_TAG_CONSTANTS_CONST.BUILDING_CONSULTANT);

            return this.mappedItem?.selectedTags
                .some(tag => tag === buildingConsultantTag?.id);
        })
    );
    this.isMobileNumberMandatory$.subscribe();
    this.teamsOptions$.subscribe();
    this.userRoleTagsOptions$.subscribe(res => this.userRoleTagsOptions = res);
}

编辑:

尝试过像这样分解 ngModel:

    <cb-selection-list name="selectedBusinessEntities"
                       [ngModel]="mappedItem.selectedBusinessEntities"
                       (ngModelChange)="selectedBusinessEntitiesChanged($event)"
                       [options]="businessEntitiesOptions$ | async"
                       [readonly]="isView()"
                       maxHeight="400px"
                       [slim]="true">
    </cb-selection-list>

ts:

public selectedBusinessEntitiesChanged(entities: number[]): void {
    this.mappedItem.selectedBusinessEntities = entities;
    this.businessEntitiesOptions$.subscribe();
    this.cdRef.detectChanges();
}

令人讨厌的是,这确实会导致this.selectedBusinessEntitiesOptionsAsDtos$运行并发出新列表(使用调试器检查)。但是用户界面没有更新。这就是为什么我添加this.cdRef.detectChanges();但它没有用。

4

1 回答 1

1

您可以使用ngModelChange事件:

(ngModelChange)="handleNgModelChangedEvent($event)

每次 ngModel 发生变化时都会触发它。$event 有效负载将保存表单字段的当前值。

更新

此外,不确定它是否会有所帮助,但您不应该在私有函数中定义您的可观察对象,而是在您声明它们的位置作为类成员:

例如:

businessEntitiesOptions$ = this.businessEntitiesLogicService.getList()
   .pipe(
      map(businessEntities => {
         orderBy(businessEntities, businessEntity => businessEntity?.name?.toLowerCase());
  })
);

代替:

public businessEntitiesOptions$: Observable<IBusinessEntityDto[]>;

你所有的 observables 也是如此......

您甚至应该能够在此类中使用 OnPush 更改检测策略。

您可以尝试添加tap(x => console.log(x))管道可观察对象,以查看它们是否按预期工作......

例如:

.pipe(
      tap(x => console.log(x)),
      map(businessEntities => {
         orderBy(businessEntities, businessEntity => businessEntity?.name?.toLowerCase()),
      tap(x => console.log(x))
})

您可能还想删除退货......除非您发现错误或其他东西,否则您不想退货。Observables 只是流。

于 2021-10-08T02:23:45.510 回答