How can a parent's method be activated only after receiving an event emitter from the child and ensuring that the parent's ngIf condition is met?

Every time the element in the child template is clicked, it triggers the method activateService(name) and emits an event with the name of the selected service using the event emitter serviceSelected. The parent component's method scrollDown(name) is then called to set the attribute serviceActive to true and scroll down to the element with the id='service-view' in the parent's template. However, there is an issue where I have to click the child element twice for the scrolling effect to be triggered in the parent component. It seems like the scroll trigger happens before the element in the parent's template becomes visible. I'm unsure how to conditionally trigger the scroll functionality only after the value of activeService has been set to true, meaning after the parent element is visible. Does anyone have a solution to this problem?

Child:

.ts:

@Output('service') serviceSelected = new EventEmitter<string>();

activateService(service: string) {
   this.serviceSelected.next(service);
}

.html:

<div class="service" (click)="activateService('service1')">...</div>

Parent:

.ts:

serviceActive!: boolean;

scrollDown(evt: string) {
   this.onServiceActivated();
   document.getElementById("service-view")?.scrollIntoView({
      behavior: "smooth",
      block: "start",
      inline: "nearest"
   });
}

onServiceActivated() {
   this.serviceActive = true;
}

.html:

<app-services (service)="scrollDown($event)"></app-services>

<!--Display only if serviceActive is true-->
<div id="service-view" *ngIf="serviceActive">
   <app-services-detail></app-services-detail>
</div>

Answer №1

Have you given this a shot?

ancestor html:

<div id="service-view" *ngIf="serviceActive">
   <app-services-detail #serviceView></app-services-detail>
</div>

ancestor ts:

@ViewhChildren("serviceView") serviceViews:QueryList<ElementRef<HTMLelement>>;

   ...

scrollDown(evt: string) {

  this.onServiceActivated();

}
   ...

ngAfterViewInit () {

   this.serviceViews.changes.pipe(
     filter( list => !!list.first ),
     tap( list => {

       list.first.nativeElement.scrollIntoView({
        behavior: "smooth",
        block: "start",
        inline: "nearest"
       });

     } )
   ).subscribe();

 }

Answer №2

To implement the scrolling functionality, use the following code within a setTimeout function:

    scrollPage(direction: string) {
     this.activateService();
     setTimeoUT(()=>{
      document.getElementById("service-view")?.scrollIntoView({
      behavior: "smooth",
      block: "start",
      inline: "nearest"
      });
     })
   }

By adding this slight delay, ensure that all elements are rendered in the DOM before executing the scrolling action.

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

Is it necessary to manually unsubscribe from observables in the main Angular component?

I'm facing a dilemma with my Observable in the root Angular (6.x) component, AppComponent. Typically, I would unsubscribe from any open Subscription when calling destroy() using the lifecycle hook, ngOnDestroy. However, since the AppComponent serv ...

Issue with MongoDB $push within an Array of Arrays: The shorthand property 'elements' does not have a value available in scope

I am encountering an issue while trying to insert data into Elements in MongoDB using TypeScript. Any suggestions on how to resolve this problem? Attempt 1 Error: I am receiving an error message stating "No value exists in scope for the shorthand property ...

Is there a way to make sure video files are downloaded instead of automatically playing in the browser window?

I have a link to a video file with various formats like mp4, 3gp, etc. When I click on the link, it opens in the same tab. Changing the target attribute to "_blank" makes the video open in a new tab. However, when I ctrl-click the link, the file s ...

Decoding the mysteries of a ZoneAwareError: A guide to unraveling the enigma

Within my Angular 2 application, I utilize a resolve guard that performs an XHR request and throws a custom error if the request fails: return this.service.getProduct (id) .catch (err => Observable.throw(new MyError(err.message, route, 500, err))); ...

Exploring the world of dynamic form creation using Angular and Mat-select options

I'm working on an Angular application and I want to create a dynamic form using Mat-select for the type selection. Depending on the chosen type, I need to be able to add or remove fields dynamically. I also want to display a specific field if the typ ...

The sourcemap for a Vue file based on TypeScript is not available due to the presence of the lang="ts" attribute

I am facing an issue where I need to transition my vue files from JavaScript to TypeScript. Currently, they have a standard structure like this: <template> ... </template> <script> ... </script> To use them with TypeScript, I le ...

How can the '!!user' syntax be utilized? What outcome does this code snippet produce?

I am looking to implement an angular route guard in my application. I came across this code snippet but I am confused about the line where user is mapped to !!user. Can someone explain the purpose of map(user => !!user) in this context? canActivate( ...

Expanding the Mui Typescript breakpoints within a TypeScript environment

Encountering a typescript error when attempting to utilize custom names for breakpoint values: Type '{ mobile: number; tablet: number; desktop: number;}' is not compatible with type '{ xs: number; sm: number; md: number; lg: number; xl: numb ...

Preventing duplicate actions on a Subject with Angular 7's rxjs debounceTime operator

While working on an Angular7 application, I encountered an issue where the KeyUp event of a numeric input was being captured by this specific HTML code: <input fxFlex type="number" formControlName="DM" (keyup)="changeDM()"> </div& ...

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

Tips for using jest.mock with simple-git/promise

I have been attempting to simulate the checkout function of simple-git/promise in my testing but without success. Here is my current approach: jest.mock('simple-git/promise', () => { return { checkout: async () => { ...

Customizing Material UI Select for background and focus colors

I am looking to customize the appearance of the select component by changing the background color to "grey", as well as adjusting the label and border colors from blue to a different color when clicking on the select box. Can anyone assist me with this? B ...

Having trouble customizing the HTML range input?

I am looking to customize the appearance of a range input slider. Specifically, I want the slider to be green for the lower portion (where the thumb has moved) and grey for the remaining section. I have successfully changed the default styles from blue and ...

Error in TypeScript React component due to prop-types ESLint in React

I'm in the process of setting up a typescript-react-eslint project and I've encountered an eslint error with this boilerplate component: import * as React from "react"; interface ButtonProps { children?: React.ReactNode, onClick?: (e: any) ...

Error encountered in Intellij for Typescript interface: SyntaxError - Unexpected identifier

I am currently testing a basic interface with the following code: interface TestInterface { id: number; text: string; } const testInterfaceImplementation: TestInterface = { id: 1, text: 'sample text' }; console.log(testInterface ...

Error: Property 'instance' is undefined and cannot be read

Trying to confirm the functionality of the following method: showSnackbar(): void { if (this.modifiedReferences.length) { const snackbar = this.snackbarService.open({ message: '', type: 'success', durat ...

Incorporating marker tags to different sections of text within a contenteditable div

The main objective of this feature is to enable users to select placeholders within message templates (variable names enclosed in %). Inspired by Dribbble The API provides strings in the following format: "Hello %First_Name% %Middle_Name% %Last_Name% ...

What is the process for inserting a new element into an Array-type Observable?

I've been working on the Angular Tour of Heroes example and I have a feature where users can add new heroes to the existing list. Here's my add hero method in hero.service.ts: addNewHero(hero : Hero) : Observable<Hero> { console.log(her ...

Utilizing TypeDoc to Directly Reference External Library Documentation

I am working on a TypeScript project and using TypeDoc to create documentation. There is an external library in my project that already has its documentation. I want to automatically link the reader to the documentation of this external library without man ...

A function's behavior will vary depending on whether it is a property of an object or not

I've been observing some peculiar behavior: In a typical scenario, TypeScript usually raises an error when an object contains too many keys, like this: type Foo = { a: string; } const a: Foo = { a: "hello", b: "foo" // Ob ...