Bonjour,

Je souhaite réaliser un loader sous forme de directive. L'idée étant que quand je dois requêter mon API, je passe simplement l'observable de ma requête et elle se charge d'afficher un loader superposé sur le composant.
Le résultat final donne ça :



Nom : Sans titre-1.png
Affichages : 650
Taille : 55,5 Ko

Tous fonctionne comme attendu, lors de l'émission de la requête HTTP vers l'API le loader se créer, se superpose avec mon élément cible. Une fois la réponse reçus le loader est détruit et les données se charge dans la liste.

Le problème est que ma requête se lance 2 fois... J'ai compris pourquoi mais je n'arrive pas à trouver une solution propre dans ma directive sans devoir modifier les différent composants l'utilisant.
Pour faire simple dans ma directive "appLoader", je souscrit à nouveau à l'Observable ce qui déclenche l'émission de la requête. Mais je suis obligé de souscrire à l'Observable car un map ne fonctionnerais pas étant donnée que lorsque ma directive reçois l'observable il a déjà été souscrit coté composant.

Avez vous une idée ?

Template (HTML)
Code html : Sélectionner tout - Visualiser dans une fenêtre à part
1
2
3
<div [appLoader]="observer">
  <app-ma-list [users]="users"></app-ma-list>
</div>

Composant
Code : Sélectionner tout - Visualiser dans une fenêtre à part
1
2
3
4
5
6
7
8
9
10
11
12
export class MaListComponent {
  users: User[] = [];
  observer: Observable<any>;
 
  constructor(private monSuperService: SuperService) {}
 
  ngOnInit() {
    (this.observer = this.monSuperService.findAll()).subscribe(users => {
      this.users = users;
    });
  }
}
Directive
Code : Sélectionner tout - Visualiser dans une fenêtre à part
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
@Directive({
  selector: '[appLoader]'
})
export class LoaderDirective implements OnInit {
  observer: Observable<any>;
 
 
  isInitialized = false;
  isReady = false;
 
  constructor() {}
 
  ngOnInit() {
    this.isInitialized = true;
 
    this.check();
  }
 
  initObserver() {
    this.startLoading();
    // this.observer.toPromise().then(() => this.stopLoading());
    // .pipe(tap(() => this.stopLoading()), map(err => this.stopLoading())); 
    this.observer.subscribe(() => this.stopLoading(), (err) => this.stopLoading());
  }
 
  check() {
    if (this.isInitialized && this.isReady) {
      this.startLoading();
    }
  }
 
  startLoading() {
    console.log('Start loading');
    // Affichage du loader avec le ContainerView ... (j'ai simplifié le code en retirant cette partie)
  }
 
  stopLoading() {
    console.log('Stop loading');
    // On détruit le loader 
  }
 
  @Input('appLoader')
  set setObservable(observer: Observable<any>) {
    // Quand on récupère l'Observable
    if (observer != null) {
      this.isReady = true;
      this.observer = observer;
      this.initObserver();
      this.check();
    }
  }
}