Voici mon code qui donne une erreur ne peut pas lire le titre de la propriété non défini.
Composant parent
import { Child } from './child.component';
@Component({
selector: 'parent',
})
export class ParentComponet implements OnInit, AfterViewInit {
constructor(){}
@ViewChild(Child) child: Child;
ngAfterViewInit(){
console.log("check data", this.child.title)
}
}
Et composant enfant est.
@Component({
selector: 'child',
})
export class ChildComponet {
public title = "hi"
constructor(){}
}
routing.module.ts est comme
{
path: "",
component: ParentComponent,
children: [
{
path: '/child',
component: ChildComponent
}
]
}
Et donne l'erreur est
ERROR TypeError: Cannot read property 'title' of undefined(…)
Je pense qu'il vous manque 'template' ou 'templateUrl' pour la création d'un composant
ParentComponent
import { ChildComponent } from './child.component'; // {ChildComponent} not {Child} as we are referencing it to the exported class of ChildComponent
@Component({
selector: 'parent',
template: `<child></child>`
})
export class ParentComponet implements OnInit, AfterViewInit {...}
ChildComponent
@Component({
selector: 'child',
template: `<h1>{{ title }}</h1>`
})
export class ChildComponent {...} // Be sure to spell it right as yours were ChildComponet - missing 'n'
UPDATE selon la clarification de l'utilisateur sur ce fil
Avait ajouté un Stackblitz Demo pour votre référence (Vérifiez la console)}
Si vous souhaitez accéder au ChildComponent rendu sous le <router-outlet>
du composant parent, vous pouvez le faire en utilisant la propriété prise en charge (activate) de router-outlet:
Une prise de routeur émettra un événement d'activation chaque fois qu'un nouveau composant est instancié
Modèle de ParentComponent
@Component({
selector: 'parent',
template: `<router-outlet (activate)="onActivate($event)"></router-outlet>`
})
export class ParentComponent {
onActivate(event): void {
console.log(event); // Sample Output when you visit ChildComponent url
// ChildComponent {title: "hi"}
console.log(event.title); // 'hi'
}
}
Le résultat sera différent en fonction de la page visitée sous les enfants de vos parents
Si vous visitez Child1Component, vous obtiendrez son instance
Child1Component {title: "hi"}
Si vous visitez Child2Component, vous obtiendrez son instance
Child2Component {name: "Angular"}
Ces résultats seront ensuite répercutés sur la console onActivate (événement) de votre ParentComponent pour que vous puissiez accéder à
Ce n'est pas comme ça que ça doit fonctionner. Vous ne pourrez obtenir que ChildComponent
dans votre ParentComponent
UNIQUEMENT si vous avez la balise <app-child></app-child>
dans votre modèle ParentComponent
.
Quelque chose comme ça:
...
<app-child></app-child>
...
Mais puisque vous utilisez le routage enfant et que la ChildComponent
se chargera sur le router-outlet
de votre ParentComponent
, vous n'y aurez pas accès à l'aide de ViewChild
.
PS: Vous n'y aurez accès qu'à l'intérieur de ngAfterViewInit
car ViewChild
ne peut être considéré comme sûr d'avoir instancié qu'après le chargement de la vue:
import { Component, OnInit, ViewChild } from '@angular/core';
import { ChildComponent } from '../child/child.component';
...
@Component({...})
export class ParentComponent implements OnInit {
@ViewChild(ChildComponent) childComponent: ChildComponent;
...
ngAfterViewInit() {
console.log(this.childComponent);
}
}
Voici un exemple de travail StackBlitz pour votre référence qui illustre votre scénario dans les deux cas.
PS: Pour obtenir les propriétés ChildComponent
dans votre ParentComponent
, avec Routing, vous devrez soit utiliser un SharedService
, soit passer la propriété ChildProperty de la route en tant que QueryParam et la lire dans votre ParentComponent à l'aide de la commande ActivatedRoute
Bien que cela n’aura pas beaucoup de sens, mais dans votre ChildComponent
, vous pouvez avoir un lien qui acheminera l’utilisateur vers le ChildComponent avec la propriété title
passée en tant que queryParam
. Quelque chose comme ça:
<a
[routerLink]="['/child']"
[queryParams]="{title: title}">
Go To Child Route With Query Params
</a>
Et dans votre ParentComponent
, y avoir accès en utilisant ActivatedRoute
comme ceci:
...
import { ActivatedRoute } from '@angular/router';
...
@Component({...})
export class ParentComponent implements OnInit {
...
constructor(
private route: ActivatedRoute,
...
) { }
ngOnInit() {
this.route.queryParams.subscribe(queryParams => {
console.log('queryParams[`title`]', queryParams['title']);
});
...
}
...
}
SharedService
Créez simplement une SharedService
avec une private
BehaviorSubject
qui serait exposée en tant que Observable
en appelant la méthode asObservable
. Sa valeur peut être définie en exposant une méthode (setChildProperty
) qui appellera essentiellement la méthode next
avec la valeur childProperty
mise à jour:
import { Injectable } from '@angular/core';
import { BehaviorSubject, Observable } from 'rxjs';
@Injectable()
export class SharedService {
private childProperty: BehaviorSubject<string> = new BehaviorSubject<string>(null);
childProperty$: Observable<string> = this.childProperty.asObservable();
constructor() { }
setChildProperty(childProperty) {
this.childProperty.next(childProperty);
}
}
Vous pouvez ensuite l'injecter à la fois dans votre ParentComponent
et dans votre ChildComponent
:
Dans ChildComponent
, définissez la valeur:
import { Component, OnInit } from '@angular/core';
import { SharedService } from '../shared.service';
@Component({
selector: 'app-child',
templateUrl: './child.component.html',
styleUrls: ['./child.component.css']
})
export class ChildComponent implements OnInit {
public title = "hi"
constructor(private sharedService: SharedService) { }
ngOnInit() {
this.sharedService.setChildProperty(this.title);
}
}
Et dans votre ParentComponent
, obtenez la valeur:
...
import { SharedService } from '../shared.service';
@Component({...})
export class ParentComponent implements OnInit {
...
constructor(
...,
private sharedService: SharedService
) { }
ngOnInit() {
...
this.sharedService.childProperty$.subscribe(
childProperty => console.log('Got the Child Property from the Shared Service as: ', childProperty)
);
}
...
}
Assurez-vous que vous avez ajouté la balise parent.component.html
dans votre modèle <child></child>
.