web-dev-qa-db-fra.com

Comment exécuter une fonction jquery dans Angular 2 après chaque chargement de composant fini

J'ai essayé tous les crochets du cycle de vie mais je n'arrive pas à obtenir le résultat souhaité. Le résultat dont j'ai besoin est de déclencher une fonction qui initialise de nombreux plugins jquery utilisés pour différents éléments sur une seule page après le chargement de chacun de ces éléments (composants).

Disons donc que vous avez cette structure.

Page d'accueil Slider Widgets Rotateurs de produit ..etc

Chacun de ces éléments a son propre composant et tous sont des enfants du composant parent de la page d'accueil.

Et ce dont j'ai besoin ici est de savoir quand tous les composants enfants et le composant parent sont chargés, donc je déclenche une fonction jquery pour initialiser chaque plugin sur la page.

22
Joseph Girgis

Vous souhaiterez utiliser le hook de cycle de vie "ngAfterViewInit", en important AfterViewInit ( https://angular.io/docs/ts/latest/guide/lifecycle-hooks.html#!#afterview ). Vous pouvez l'utiliser comme indiqué ci-dessous:

Installation:

    tsd install jquery --save

ou

    typings install dt~jquery --global --save

Utilisation:

    import { Component, AfterViewInit } from '@angular/core';
    import * as $ from 'jquery';

    ngAfterViewInit() {
        this.doJqueryLoad();     
        this.doClassicLoad();

        $(this.el.nativeElement)
            .chosen()
            .on('change', (e, args) => {
                this.selectedValue = args.selected;
            });
    }

    doClassicLoad() {
      // A $( document ).ready() block.
      $( document ).ready(function() {
          console.log( "Unnecessary..." );
      });      
    }

    // You don't need to use document.ready... 
    doJqueryLoad() {
        console.log("Can use jquery without doing document.ready")
        var testDivCount = $('#testDiv').length;
        console.log("TestDivCount: ", testDivCount);
    }

Voici un plongeur pour un exemple: http://plnkr.co/edit/KweZYO9hk9Dz8pqDK77F?p=info

24
Dan Weber

Le moyen le plus efficace que j'ai trouvé est d'utiliser setTimeout avec un temps de 0 à l'intérieur du constructeur de page/composant. Cela permet d'exécuter jQuery dans le prochain cycle d'exécution après Angular a fini de charger tous les composants enfants.

export class HomePage {
    constructor() {
        setTimeout(() => {
            // run jQuery stuff here
        }, 0);
    }
}

Mettre le setTimeout à l'intérieur de la méthode ngOnInit a également fonctionné pour moi.

export class HomePage {
    ngOnInit() {
        setTimeout(() => {
            // run jQuery stuff here
        }, 0);
    }
}
16
Urgo

qu'en est-il de

bootstrap(...).then(x => {
  ...
})

sinon, je suppose que ngAfterViewInit() de votre composant racine est un hook de cycle de vie qui correspond à vos besoins, mais vous avez déclaré que vous aviez déjà tout testé ...

mise à jour

bootstrap() ou ngAfterViewInit() sur le composant racine ne peut être utilisé que pour la charge initiale. Pour les composants ajoutés ultérieurement, la ngAfterViewInit() des composants ajoutés peut être utilisée.

4

J'ai eu le même problème ici. J'ai trouvé 2 solutions, même si elles ne sont pas les meilleures:

1 - Implémentez afterViewChecked pour vérifier si le plugin jquery est lancé, puis utilisez une variable pour contrôler son initialisation. C'est la voie difficile car afterViewChecked est appelé plusieurs fois.

2 - J'ai changé certains éléments pour qu'ils soient cachés en utilisant une propriété cachée au lieu de ngIf. Avec caché, je pourrais initialiser tous les plugins jquery en utilisant afterViewInit et les faire fonctionner même mes objets sont cachés.

setTimeout ne fonctionnait pas lors de l'utilisation de ngIf. Il se déclenche avant que le contenu ne soit restitué.

1
Cristal Embalagens

Une solution possible serait de vous abonner sur zone.onStable ou zone.onMicrotaskEmpty

ngAfterViewInit() {
  this.zone.onStable.first().subscribe(() => {
    debugger;
  });
}

ou

ngOnInit() {
  this.service.getData().subscribe(() => {
    this.data = data;
    this.zone.onMicrotaskEmpty.first().subscribe((data) => {
      $(someElem).plugin();
    });
  });
}

Voir également

1
yurzui