web-dev-qa-db-fra.com

Angular Composant 6 recharges de l'auditeur de défilement

Pour exposer cela le plus simplement possible, voici mon scénario.

1) J'ai un composant parent qui a une ViewContainerRef pour charger dynamiquement un composant dans le parent. Pour mon cas d'utilisation, le parent est une page de titulaire vide qui se remplace de manière dynamique par une autre page dépendant d'un ensemble de variables.

<ng-template #dynamic></ng-template>

2) Le composant enfant a une div de défilement horizontal qui ressemble à ce qui suit:

<div id="carousel" (scroll)="onScroll($event)"> <!-- List of components --> </div>

Chaque fois qu'il fait défiler AVEC l'écouteur (scroll), il recharge le composant parent. Par conséquent, la position de défilement revient toujours à 0 car elle a été rechargée.

Cependant, si je supprime l'écouteur (scroll), la div défile sans problème. Le problème est que je souhaite modifier dynamiquement les éléments de la page en fonction de la position du défilement horizontal.

Quelqu'un a-t-il des idées à propos des problèmes pouvant survenir avec les composants intégrés et un écouteur à défilement? Serait grandement apprécié!

7
Brayden

Je soupçonne que la variable onScroll déclenche le détecteur de changement d'Angular (comme le suggèrent les commentaires), ce qui, pour une raison quelconque, détermine que la page est sale - ce qui déclenche un nouveau tracé de la page. Si tel est le cas, je soupçonne que le rafraîchissement réinitialise le carrousel div.

Pour confirmer cette suspicion, vous pouvez modifier la ChangeDetectionStrategy de votre composant gênant. ChangeDetectionStrategy.OnPushne redessinera votre composant que si les données liées à un @Input() (comme data ci-dessous) changent OR si vous le spécifiez explicitement aussi.

@Component({
  selector: 'app-neat',
  templateUrl: './neat.component.html',
  // Add this line to your component
  changeDetection: ChangeDetectionStrategy.OnPush 
})
export class NeatComponent {
  @Input() data: string[];
}

Cela signifie que lorsque vous souhaitez redessiner le composant, vous devez indiquer explicitement à Angular de le faire. Vous pouvez faire ça comme ça:

@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();
  }
}

Vous pouvez trouver plus d'informations ici: https://alligator.io/angular/change-detection-strategy/

Cela devrait vous permettre d'avoir un contrôle plus fin sur le contenu de votre page redessiné lorsque l'événement de défilement est déclenché.

Si vous publiez plus de code, nous pourrons peut-être fournir une réponse plus précise.

2
Pearman

Je ne sais pas si vous injectez des composants comme celui-ci, mais c’est ce que j’essaie de résoudre.

J'ai utilisé le rendu pour écouter le défilement d'événements de fenêtre dans le composant enfant.

StackBlitz

Ne fais pas attention à mon style

2
karoluS

Si vous utilisez un objet window directement depuis le composant enfant, le zéro sera toujours 

puisque vous voulez utiliser un événement window scroll from child, vous pouvez utiliser un objet event pour obtenir la valeur ScrollY

Child.html

 <p (window:scroll)="onScroll($event)" >
    demo Scroll Value{{scrollValue}}
    </p>

child.component.ts

 onScroll($e){
    this.scrollValue=$e.path[1].scrollY;
    console.log($e.path[1].scrollY);
  }

Exemple: https://stackblitz.com/edit/viewcontainer

0
Chellappan