Angular 2: Capturing scroll events from the parent element within a Directive

One of the challenges I encountered is with a directive called [appInvalidField] that functions like a custom tooltip for validation purposes. To ensure it appears above everything else within dialogs, I attach it to the body and position it near the relevant field.

The issue arises when scrolling comes into play. I realized that I need to dynamically adjust the tooltip's position based on scroll events triggered by the form. The tricky part is figuring out how to achieve this adjustment within the directive file without altering the existing HTML structure. Below is an example of how the directive is used in a form:

<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>

Answer №1

Presented here is a custom directive that tracks all scroll events from the current position upwards:

@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() {
        // Initialize the listener once everything is set up
        this.ready$.next();
    }
}

In essence, this directive traverses the DOM structure upwards, attaching scroll event listeners to each container and consolidating them into a single stream. I utilize it for handling similar scenarios, however there's a known limitation where querying any DOM positioning information during fast scrolling can cause delayed updates. To mitigate this, one solution is to position the element absolutely instead of fixed, as this approach minimizes recalculations triggered by body scrolls in most instances.

Answer №2

For a more sophisticated approach, consider utilizing the IntersectionObserver, which is demonstrated in this insightful post: How to check if element is visible after scrolling?

To implement this with a directive, you can create something similar to the following:

@Directive({
  selector: '[fixedscroll]'
})
export class FixedscrollDirective{
@Input() windowOnly = false;
constructor(
    @Inject(ElementRef) {nativeElement}: ElementRef<Element>,
) {
    var observer = new IntersectionObserver(onIntersection, {
      root: null,   // default is the viewport
      threshold: .5 // percentage of target's visible area. Triggers "onIntersection"
    })

    // callback is called on intersection change
    function onIntersection(entries, opts){
      entries.forEach(entry =>
        entry.target.classList.toggle('visible', entry.isIntersecting)
      )
    }

    // Use the observer to observe an element
    observer.observe( nativeElement )
}
}

Similar questions

If you have not found the answer to your question or you are interested in this topic, then look at other similar questions below or use the search

Encountering a TS(2322) Error while Implementing Observables in Angular 12

Exploring the intricacies of Angular 12 framework, I find myself encountering a hurdle in my learning journey. The tutorial I am following utilizes the Observable class to query fixed data asynchronously. However, an unexpected ts(2322) error has surfaced ...

How to connect a form component object with a parent object in Vue3 using v-model and the Options API?

My inquiry is quite straightforward. I am exploring the official Vue documentation that delves into v-model arguments in relation to forms within a child component. Here is the code snippet I am referring to: (App.Vue) <script> import UserName from & ...

Distilling the Essence of "Deity" in Handling Runtime Errors

Working with a client who has a unique "God" component for creating form fields can be quite challenging. The complexity arises from the fact that we are using material design for non-mobile platforms and Ionic for mobile platforms. This special component ...

Angular Tip: Display data in a dropdown using a select element

When I have two select elements and want to display values if they exist: page.ts import { Component } from '@angular/core'; @Component({ selector: 'my-app', templateUrl: './app.component.html', styleUrls: ['./app ...

The NgZone reference error caused the prerendering to fail

I am facing challenges with the implementation of NgZones. Despite defining NgZone, I keep encountering this error: "NodeInvocationException: Prerendering failed because of error: ReferenceError: NgZone is not defined" Below is my app.error-handle.ts file ...

Issue encountered while attempting to utilize a basic redux reducer to define a boolean value, regarding a mismatch in overrides

Currently, I am working on a project to enhance my understanding of Redux and Typescript. I am still navigating through the learning curve in this area. Based on what I have learned from a book, I have established a "slice" that includes definitions for r ...

Error in Angular6: Why can't handleError read injected services?

It appears that I am facing an issue where I cannot access a service injected inside the handleError function. constructor(private http: HttpClient, public _translate: TranslateService) { } login(user: User): Observable<User> { ...

Handling onChange events for several typescript <Select> elements

As a non-TS developer, I'm delving into the realm of multiple selects and dropdown menus with Material-UI's select component. Progressing from a basic setup, I successfully implemented a single select but now face a challenge in adding another dr ...

The favicon appears broken upon opening a new tab

Usually, I use a favicon PNG file for my website. It works perfectly and I can see my favicon on the browser tab. However, when I open a PDF document in a new page from my Angular app, I notice that there is a broken icon on the browser tab. Here is how I ...

Developing a custom camera system for a top-down RPG game using Javascript Canvas

What specific question do I have to ask now? My goal is to implement a "viewport" camera effect that will track the player without moving the background I am integrating websocket support and planning to render additional characters on the map - movement ...

Tips for eliminating Ref upon exiting the screen on React / React Native?

When navigating back in React / React Native, I am encountering keyboard flickering caused by the presence of Ref on the screen. I would like to remove it before leaving the screen. The code snippet I am using is as follows: // To focus on the input fie ...

Using Angular 2 with Material 2 to create dynamic checkbox bindings

I am currently working on an Angular 2 (2.4.3) application that utilizes Material (2.0.0-beta.1), and I have encountered a challenge with bindings on checkboxes. My goal is to have a checkbox reflect a boolean value in my component and toggle the value wh ...

Navigating with hashtags in Angular2 and anchors does not change the page position

I recently came across a helpful post that showed me how to append a fragment to the URL. Angular2 Routing with Hashtag to page anchor Although the fragment is successfully added, I'm encountering an issue where the page does not scroll to the speci ...

Extracting arrays from JSON in Angular: A step-by-step guide

I am currently working with Angular2 (version 5) and facing an issue. I am able to make an HTTP request and receive JSON data. While I know how to access and use individual values, I am struggling with accessing and extracting the two arrays inside an elem ...

Create a const assertion to combine all keys from an object into a union type

I am working with an object similar to this (demo link): const locations = { city: {name: 'New York'}, country: {name: 'United States'}, continent: {name: 'North America'} } as const My goal is to create a union t ...

I'm encountering an error in TestCafe that says "TypeError: Cannot read properties of undefined (reading 'match')". Which specific segment of my code is causing this issue?

retrieveUrlFromEmailData(emailData:any){ const emailContent = emailData.email_text; const urlPattern = /(https?:\/\/[^\n]*)/; const foundUrl = emailContent.match(urlPattern)[0]; return foundUrl } ...

Utilizing handpicked information in Angular: A beginner's guide

Being new to Angular and programming in general, I am currently navigating through the intricacies of Angular and could use some guidance on utilizing selected data. For instance, I would like to use a personnel number view image here and send it to the b ...

Loading tabs dynamically in Angular 2 based on header click event

I successfully created a custom tab component using Angular 2, and it is functioning well with the following usage: <us-tab-verticle> <vtab-content [tabTitle]="'Basic Information'"><basic-info> </basic-info></vtab- ...

Test Failure: Attempt to access 'componentInstance' property on a non-existent value

I am facing an issue where my unit tests are working fine with the angular2-seed project, but not with my own project that closely resembles angular2-seed. The only difference between my project and angular2-seed is that I use a gulpfile.ts without the to ...

Tips for presenting SVG symbols using Interpolation within Angular 7 from a JSON document

When it comes to displaying content in Angular 7 components, JSON is used. However, I have encountered a problem while trying to incorporate SVG icons from our UX team into the component using JSON. Using the img tag restricts me from applying a CSS class ...