To lay this out as simply as possible, here's my scenario.
1) I have parent component that has a ViewContainerRef
to dynamically load in a component within the parent. For my use case, the parents is an empty holder page that replaces itself dynamically with another page dependent on a set of variables.
<ng-template #dynamic></ng-template>
2) The child component has a horizontal scroll div that looks similar to the following:
<div id="carousel" (scroll)="onScroll($event)">
<!-- List of components -->
</div>
Any time it is scrolled WITH the (scroll)
listener, it reloads the parent component and therefore the scroll position always bounces back to 0 because it was reloaded.
However, if I remove the (scroll)
listener the div scrolls without an issue. The problem is, I want to dynamically change items on the page based on the horizontal scroll position.
Does anyone have any thoughts on issues that could arise with embedded components and a scroll listener? Would be GREATLY appreciated!
I suspect that the onScroll
is triggering Angular's change detector (like the comments suggest), which for some reason decides the page is dirty -- which triggers a redraw of the page. If that is the case, I suspect the redraw resets the carousel div.
To confirm this suspicion you can change the ChangeDetectionStrategy
on your troublesome component. ChangeDetectionStrategy.OnPush
will only redraw your component if the data bound to an @Input()
(like data
bellow) changes OR if you explicitly tell it too.
@Component({
selector: 'app-neat',
templateUrl: './neat.component.html',
// Add this line to your component
changeDetection: ChangeDetectionStrategy.OnPush
})
export class NeatComponent {
@Input() data: string[];
}
That means that when you do want the component to redraw you need to explicitly tell Angular to do so. You can do that like so:
@Component({
selector: 'app-neat',
templateUrl: './neat.component.html',
changeDetection: ChangeDetectionStrategy.OnPush
})
export class ChildComponent {
@Input() data: string[];
// Inject the ChangeDetectorRef into your component
constructor(private cd: ChangeDetectorRef) {}
refresh() {
// Manually tell Angular to detect changes and redraw the screen
this.cd.detectChanges();
}
}
You can find more info here: https://alligator.io/angular/change-detection-strategy/
This should allow you to have fine grained control over what content on your page redraws when the scroll event is triggered.
If you post more code, we might be able to provide a more specific answer.
I don't know if you are injecting components like this but this is my try to take this problem.
I used renderer to listen to window event scroll in child component.
StackBlitz
Don't mind my styling
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With