角度2:侦听指令中父元素的滚动事件

时间:2019-03-15 08:53:31

标签: angular typescript

我有一个验证指令[appInvalidField],就像自定义工具提示一样。由于我需要在对话框中使用它并将其显示在所有其他内容之上,因此我将其附加在必须显示在旁边的字段附近的正文和位置上。

但是滚动存在问题。我需要听窗体上的滚动事件并更改工具提示位置。我该如何做而不更改我的html?就在指令文件中。这是我的HTML(在表单中使用它的示例):

<form #ngForm="ngForm" [formGroup]="form" (ngSubmit)="onSave()">
  <div class="form--edit">
    <div class="form__group p-grid">
         <label class="p-col-12 form__label">{{'substance.IUPACName-title' | translate}}</label>
         <div appInvalidField="names">
               <span *appInvalidFieldType="'required'" [translate]="'substance.IUPACName-field-required'"></span>
                <span *appInvalidFieldType="'maxlength'"
                                [translate]="'substance.IUPACName-field-maxlength'"></span>
          </div>
          <input class="p-col" pInputText [maxLength]="formService.maxLength" appAutofocus  formControlName="names" />
    </div>
  </div>
</form>

1 个答案:

答案 0 :(得分:2)

这是一条指令,用于订阅从当前开始的所有滚动事件:

@Directive({
    selector: '[allParentsScroll]',
})
export class AllParentsScrollDirective implements OnInit {
    @Output('allParentsScroll')
    readonly allParentsScroll$: Observable<Event>;

    private readonly ready$ = new Subject<void>();

    constructor(
        @Inject(ElementRef) {nativeElement}: ElementRef<Element>,
    ) {
        const eventTargets: EventTarget[] = [window, nativeElement];

        while (nativeElement.parentElement) {
            nativeElement = nativeElement.parentElement;
            eventTargets.push(nativeElement);
        }

        const allScroll$ = merge<Event>(
            ...eventTargets.map<Observable<Event>>(element => fromEvent(element, 'scroll')),
        );

        this.allParentsScroll$ = this.ready$.pipe(swithMapTo(allScroll$));
    }

    ngOnInit() {
        // Kickstart the listener when everything is ready
        this.ready$.next();
    }
}

基本上,我们只是向上移动DOM树,订阅每个容器上的滚动事件并将其全部合并为一个大流。我在与您相同的情况下使用它,但是存在一个已知的问题,当您尝试定位元素时,查询任何DOM位置(偏移量,客户端矩形等)都会导致重排,因此即使您尝试更新自己的元素元素在requestAnimationFrame中的位置-在快速滚动时仍会落后一点。据我所知,这是没有解决的,我所做的是将其绝对定位而不是固定定位,因此正文滚动实际上不会更改任何计算-在大多数情况下,此问题可最小化。