2017-10-09 3 views
1

J'ai un composant qui est destiné à être utilisé dans un autre composant qui l'enveloppe pour l'itinéraire. Ce composant a un événement de sortie qui déclenche la navigation retour vers la route parent:ne peut pas résoudre la promesse en cas de sortie pour le composant utilisé dans le routeur

@Component({ 
    selector: 'hello', 
    template: ` 
    <ng-content></ng-content> 
    <button (click)="back($event)">Back</button> 
    ` 
}) 
export class HelloComponent { 
    @Output() helloBack = new EventEmitter(); 

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

    back($event) { 
    this.router.navigate(['./'], { relativeTo: this.route.parent }) 
     .then(() => { 
     this.helloBack.emit($event); 
     }); 
    } 
} 

Ensuite, je crée le composant wrapper à utiliser dans la route:

@Component({ 
    template: ` 
    <hello (helloBack)="onBack()"> 
    <h1>Hello World!</h1> 
    </hello> 
    ` 
}) 
export class HelloRouteComponent { 
    onBack() { 
    console.log('back!!!'); 
    } 
} 

Enfin, je charge cela dans le routage Module:

RouterModule.forRoot([ 
    { 
    path: 'hello', 
    component: HelloRouteComponent 
    } 
]) 

Quand je vais à la route /hello les charges HelloRouteComponent bien. Lorsque je clique sur le bouton de retour, il accède à la route mère, mais il ne se connecte pas quoi que ce soit à la console après avoir navigué avec succès là-bas.

Pourquoi ne pas la promesse résoudre? Qu'est-ce qui me manque pour que ça marche?

Démo:https://stackblitz.com/edit/angular-rewax8?file=app%2Fapp.component.ts

Répondre

1

Je crois que c'est parce que le temps router.navigate() est résolu, et helloBack.emit() est invoquée, la liaison <hello (helloBack)="onBack()"> n'existe plus depuis HelloComponent est déjà détaché. Vous pouvez utiliser un service partagé qui déclare un champ Subject<T> (un remplacement naturel pour @Output événement/EventEmitter). Et utilisez ce sujet à la place. Est-ce que ça fait du sens?


Le service peut regarder comme suit:

@Injectable() 
export class HelloContextService { 

    private _helloBackSubject = new Subject<any>(); 
    $helloBack: Observable<any>; 

    constructor() { 
     this.$helloBack = this._helloBackSubject.asObservable(); 
    } 

    emitHelloBack(payload: any): void { 
     this._helloBackSubject.next(payload); 
    } 
} 

Vous aurez besoin de l'injecter dans vos deux composants. HelloComponent peut alors appeler this.emitHelloBack($event), et l'autre composant peut souscrire à l'$helloBack observable.

HelloComponent:

export class HelloComponent { 

    constructor(private router: Router, 
     private route: ActivatedRoute, 
     private helloContextService: HelloContextService) { 
    } 

    back($event) { 
     this.router.navigate(['./'], { relativeTo: this.route.parent }) 
      .then(() => { 
       this.helloContextService.emitHelloBack($event); 
      }); 
    } 
} 

L'autre composant:

export class HelloRouteComponent { 
    constructor(private helloContextService: HelloContextService) { 
     this.helloContextService 
      .$helloBack 
      .subscribe(payload => { 
       // ... 
      }); 
    } 
} 
+0

Merci pour la réponse rapide. Pouvez-vous démontrer comment ce service fonctionnerait? – elclanrs

+0

Regardez le code. :) –

+0

Je vois ... Pas sûr que cela fonctionnera pour mon cas d'utilisation, parce que le composant route est créé par l'utilisateur qui consomme mon composant, et je n'ai aucun contrôle sur cela, et je ne veux pas que l'utilisateur ait pour injecter un service, et ainsi de suite. – elclanrs

0

Dans votre application vous expose un émetteur d'événements en définissant la variable @Output de type et vous rattrapent que l'enfant compoenent. Tout semble bien.

Je pense que le problème peut être this.router.navigate ne reçoit pas appelé ou onBack(event: EditEvent) vous n'avez pas transmis le paramètre à la fonction appelée.

@Component({ 
    selector: 'hello', 
    template: ` 
    <ng-content></ng-content> 
    <button (click)="back($event)">Back</button> 
    ` 
}) 
export class HelloComponent { 
    @Output() helloBack = new EventEmitter(); 

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

    back($event) { 
    this.helloBack.emit({status: 'gone back'}); 
    this.router.navigate(['./'], { relativeTo: this.route.parent }) 
     .then(() => { 
     this.helloBack.emit($event); 

     }); 
    } 
} 

paramètre ajouter à la méthode onBack

@Component({ 
    template: ` 
    <hello (helloBack)="onBack()"> 
    <h1>Hello World!</h1> 
    </hello> 
    ` 
}) 
export class HelloRouteComponent { 

    onBack(event: EditEvent) { 
    console.log('back!!!'); 
    } 
} 
Finally, I load this in the routing module: 

RouterModule.forRoot([ 
    { 
    path: 'hello', 
    component: HelloRouteComponent 
    } 
]) 

Je pense que peu de débogage résoudra votre problème.