2
votes

Rechargement de l'itinéraire enfant sans obtenir de données de l'itinéraire parent

J'ai un composant 'panneau' qui a deux tableaux de bord de routes enfants et des vacances. Ces deux routes enfants obtiennent des données sur leur ngOnInit du service de composant parent.

Tout fonctionne correctement et le tableau de bord se charge avec des données si nous allons de manière normale, mais si nous rechargeons la route enfant, il n'obtient pas le parent données de service.

Comment résoudre ce problème?

Module de routage: -

export class DashboardComponent {
/** dashboard ctor */

private userDetails = {
    name:""
}
constructor(private panelService: PanelService) {

}
ngOnInit() {
    //console.log(this.panelService.userDetails.profileDetails[0].name);
    this.userDetails.name=this.panelService.userDetails.profileDetails[0].name
}

panelComponent.ts: - p >

export class PanelComponent implements OnInit {

constructor(private panelService: PanelService, route: ActivatedRoute, private router: Router) {

}

ngOnInit() {
    this.panelService.getUserProfile().subscribe(
        res => {
            this.panelService.userDetails = res;
            this.router.navigate(['panel/dashboard'])
        },
        err => {
            console.log(err);
        },
    ); 
}

DashboardComponent.ts: -

{
    path: 'panel',
    component: PanelComponent,
    canActivate: [AuthGuard],
    children: [

        {
            path: 'dashboard',
            component: DashboardComponent,

        },
        {
            path: 'holidays',
            component: HolidaysComponent
        }
    ]
}


0 commentaires

3 Réponses :


1
votes

ngOnInit est appelé lorsqu'un composant est créé. Probablement lorsque vous visitez l'URL du problème pour la première fois, les deux composants sont en cours de création, mais lorsque vous revisitez, seul l'enfant est en cours de création car le parent n'a jamais été détruit. Vérifiez quand ngOnInit et ngOnDestroy sont déclenchés pour les 2 composants.

Vous devrez peut-être refactoriser votre code.


2 commentaires

en fait, j'ai une réponse ajax du composant parent qui est utilisé dans tous les composants enfants. est-ce mal de partager cela via un service? comment puis-je procéder avec ce scénario?


vous pouvez placer les appels au service dans le composant enfant (et si vous le souhaitez mettre en cache la réponse) - ou vous pouvez faire la demande dans un résolveur - ou la réponse de Neils semble prometteuse, ce qui est documenté ici - angular.io/guide/...



1
votes

Il est bon de partager des données entre les composants lorsque ces composants sont rendus pour une seule route.

Tout fonctionne bien

Dans ce cas, vous êtes enfants, les composants seront rendus après le composant Parent, mais parfois vous avez besoin de rafraîchir à partir de la route enfant, alors vous devez appeler la méthode de service elle-même à partir du composant enfant.

Je pense que vous devez refactoriser votre composant enfant comme ci-dessous

ngOnInit() {
  if(!this.panelService.userDetails) { 
     this.panelService.getUserProfile().subscribe( res => {
        this.panelService.userDetails = res;
      },
      err => {
        console.log(err);
      }); 
  }
  this.userDetails.name = this.panelService.userDetails.profileDetails[0].name;
}

BehaviorSubject est une bonne approche pour vos besoins. Mais si vous rechargez la route enfant elle-même, il est possible que vous perdiez également les données dans behaviorSubject oject.

Si vous pensez que vous avez même besoin des données la route enfant est actualisée, vérifier les données du composant enfant est une meilleure approche (du moins à mon avis).


3 commentaires

après router.navigate (['panel / dashboard']), le ngOnit du tableau de bord, fonctionne à nouveau?


Salut, votre solution fonctionnait bien, mais j'ai un doute. le service du composant parent n'a-t-il pas été appelé pendant le rechargement de l'enfant? ou c'est simplement parce que les appels ajax des parents ne sont pas terminés, de sorte que je ne reçois pas de données à l'enfant? votre solution fonctionne bien, mais je réécris maintenant les codes dans tous les composants pour vérifier si les données des composants parents sont présentes ou non. est-ce un bon moyen?


oui, je peux atteindre la même fonctionnalité avec le sujet du comportement, mais selon votre opinion si l'enfant est rechargé par les données du parent, je dois vérifier si les données sont présentes ou non?



1
votes

Vous feriez mieux d'utiliser un BehaviorSubject dans votre service et de vous abonner à son observable, votre service ressemblerait à:

{{panelService.userDetails$ | asynchronous}}

Puis changez votre Fonction getUserProfile

this.panelService.userDetails$.subscribe(value => this.userDetails = value);

Et votre PanelComponent

export class PanelComponent implements OnInit {

  constructor(private panelService: PanelService, route: ActivatedRoute, private router: Router) {
  }

  ngOnInit() {
    this.panelService
      .getUserProfile().subscribe(
        res => {
          this.router.navigate(['panel/dashboard'])
        },
        err => {
         console.log(err);
        },
    ); 
  }

Votre DashboardComponent va alors s'abonner à l'observable sur le service

getUserProfile() {
  return this.http.get(‘uri-to-server-resource’).pipe(
    tap(res => this.userDetailsSubject.next(res))
  );
}

Ou l'utiliser directement dans votre template

export class PanelService {
  private userDetailsSubject = new BehaviorSubject(null);
  userDetails$: Observable<UserDetail> = this.userDetailsSubject.asObservable();
}

p >


5 commentaires

J'essaierai ceci. mais cela a-t-il initié des appels ajax sur chaque chargement de route enfant, si je m'abonne? j'ai fait comme ci-dessus pour éviter cela


Non, vous lancez toujours l'appel Ajax dans votre parent appelant getUserProfile , la réponse est programmée sur le BehaviorSubject puis chaque fois que l'enfant s'abonne à panelService.userDetails $ ils recevront la dernière valeur


Je n'ai pas compris comment vous utilisez "this.userDetailsSubject.next (res);" ce fichier de service interne? mon abonnement à ce service se fait dans panelComponent.ts et res y arrive.


J'ai essayé de cette façon tout à l'heure, mais je suis toujours nul lors du rendu initial de l'application. pouvez-vous jeter un œil à cette question lien cela semble être le problème.


Oui, c'est correct, il sera null jusqu'à ce que l'appel HTTP asynchrone ait répondu. Lorsque vous créez le BehaviorSubject , vous fournissez au constructeur une valeur initiale (dans le cas ci-dessus, c'est null , la valeur suivante sera la réponse du serveur, le lien ci-dessus vous permettra de faire la même chose à partir d'un résolveur qui se terminera avant de naviguer vers votre route parent