Angular 6 @Viewchild is not working with lazy loading
up vote
7
down vote
favorite
Here is my code that gives error cannot read property title undefined.
Parent Component
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)
}
}
And Child Component is.
@Component({
selector: 'child',
})
export class ChildComponet {
public title = "hi"
constructor(){}
}
routing.module.ts is like
{
path: "",
component: ParentComponent,
children: [
{
path: '/child',
component: ChildComponent
}
]
}
And Gives error is
ERROR TypeError: Cannot read property 'title' of undefined(…)
javascript angular angular6 lazy-loading
add a comment |
up vote
7
down vote
favorite
Here is my code that gives error cannot read property title undefined.
Parent Component
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)
}
}
And Child Component is.
@Component({
selector: 'child',
})
export class ChildComponet {
public title = "hi"
constructor(){}
}
routing.module.ts is like
{
path: "",
component: ParentComponent,
children: [
{
path: '/child',
component: ChildComponent
}
]
}
And Gives error is
ERROR TypeError: Cannot read property 'title' of undefined(…)
javascript angular angular6 lazy-loading
2
can you share your parent.component.html file ?
– hana_wujira
Dec 5 at 7:48
1
Try with something like this... In your parent.component html:<child #myChildComponent></child>
and in your parent component typescript:@ViewChild('myChildComponent') child: Child;
– Deadpool
Dec 5 at 8:19
add a comment |
up vote
7
down vote
favorite
up vote
7
down vote
favorite
Here is my code that gives error cannot read property title undefined.
Parent Component
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)
}
}
And Child Component is.
@Component({
selector: 'child',
})
export class ChildComponet {
public title = "hi"
constructor(){}
}
routing.module.ts is like
{
path: "",
component: ParentComponent,
children: [
{
path: '/child',
component: ChildComponent
}
]
}
And Gives error is
ERROR TypeError: Cannot read property 'title' of undefined(…)
javascript angular angular6 lazy-loading
Here is my code that gives error cannot read property title undefined.
Parent Component
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)
}
}
And Child Component is.
@Component({
selector: 'child',
})
export class ChildComponet {
public title = "hi"
constructor(){}
}
routing.module.ts is like
{
path: "",
component: ParentComponent,
children: [
{
path: '/child',
component: ChildComponent
}
]
}
And Gives error is
ERROR TypeError: Cannot read property 'title' of undefined(…)
javascript angular angular6 lazy-loading
javascript angular angular6 lazy-loading
edited Dec 5 at 8:07
Deadpool
350119
350119
asked Dec 5 at 7:44
Ricky
1732211
1732211
2
can you share your parent.component.html file ?
– hana_wujira
Dec 5 at 7:48
1
Try with something like this... In your parent.component html:<child #myChildComponent></child>
and in your parent component typescript:@ViewChild('myChildComponent') child: Child;
– Deadpool
Dec 5 at 8:19
add a comment |
2
can you share your parent.component.html file ?
– hana_wujira
Dec 5 at 7:48
1
Try with something like this... In your parent.component html:<child #myChildComponent></child>
and in your parent component typescript:@ViewChild('myChildComponent') child: Child;
– Deadpool
Dec 5 at 8:19
2
2
can you share your parent.component.html file ?
– hana_wujira
Dec 5 at 7:48
can you share your parent.component.html file ?
– hana_wujira
Dec 5 at 7:48
1
1
Try with something like this... In your parent.component html:
<child #myChildComponent></child>
and in your parent component typescript: @ViewChild('myChildComponent') child: Child;
– Deadpool
Dec 5 at 8:19
Try with something like this... In your parent.component html:
<child #myChildComponent></child>
and in your parent component typescript: @ViewChild('myChildComponent') child: Child;
– Deadpool
Dec 5 at 8:19
add a comment |
3 Answers
3
active
oldest
votes
up vote
10
down vote
accepted
I think you are missing 'template' or 'templateUrl' in relevance to creating a Component
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 as per the user's clarification on this thread
Had added a Stackblitz Demo for your reference (Check the console)
If you want to access the ChildComponent that is rendered under the Parent Component's <router-outlet>
you can do so by utilizing (activate) supported property of router-outlet:
A router outlet will emit an activate event any time a new component is being instantiated
Angular Docs
ParentComponent's Template
@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'
}
}
The result will differ based on the visited page under your parent's children
If you visit Child1Component you will get its instance
Child1Component {title: "hi"}
If you visit Child2Component you will get its instance
Child2Component {name: "Angular"}
These results will then be reflected on your ParentComponent's onActivate(event) console for you to access
Hiii @KShewengger...thanks for your time....Actually I have multiple child components so I am useing <router-outlet></router-outlet> to render child view..
– Ricky
Dec 5 at 9:07
1
Hi @Ricky had updated my answer :) Since you can't use @ViewChild() on your ParentComponent since your ChildComponent is not a direct descendant or physically included on your Parent Component's Template. So the workaround, since you are loading them on your router-outlet, why not try to use its (activate) supported property of router-outlet
– KShewengger
Dec 5 at 9:46
1
Thanks for your answer....its too helpful for me and others also...
– Ricky
Dec 5 at 10:46
add a comment |
up vote
3
down vote
That's not how it's supposed to work. You'll be only able to get the ChildComponent
in your ParentComponent
ONLY if you have the <app-child></app-child>
tag in your ParentComponent
Template.
Something like this:
...
<app-child></app-child>
...
But since you're using child routing, and the ChildComponent
will load on the router-outlet
of your ParentComponent
you won't have access to that using ViewChild
PS: You'll only have access to it inside ngAfterViewInit
as ViewChild
can only be considered safe to have instantiated after the View has loaded:
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);
}
}
Here's a Working Sample StackBlitz for your ref that illustrates your scenario in both the cases.
PS: To get the ChildComponent
properties in your ParentComponent
, with Routing, you'll have to either use a SharedService
or you'll have to pass the ChildProperty in the route as a QueryParam and read it in your ParentComponent using the ActivatedRoute
UPDATE:
Sharing Data using Route Query Params:
Although this won't make much sense, but in your ChildComponent
, you can have a Link that would route the user to the ChildComponent with the title
property passed as a queryParam
. Something like this:
<a
[routerLink]="['/child']"
[queryParams]="{title: title}">
Go To Child Route With Query Params
</a>
And in your ParentComponent
have access to it using ActivatedRoute
like this:
...
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']);
});
...
}
...
}
Using a SharedService
Just create a SharedService
with a private
BehaviorSubject
that would be exposed as an Observable
by calling the asObservable
method on it. It's value can be set by exposing a method(setChildProperty
) that will essentially call the next
method with the updated childProperty
value :
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);
}
}
You can then inject it both in your ParentComponent
and in your ChildComponent
:
In ChildComponent
set the value:
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);
}
}
And in your ParentComponent
get the value:
...
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)
);
}
...
}
add a comment |
up vote
2
down vote
Make sure inside your parent.component.html
template you've added the <child></child>
tag.
Hiii @Morema...thanks for your time....Actually I have multiple child components so I am using <router-outlet></router-outlet> to render child view..
– Ricky
Dec 5 at 9:29
No worries, just trying to help and learn along the way. @KShewengger explained intelligently in his post and I also got to learn :)
– Morema
Dec 5 at 10:17
Thanks @Morema for helping me to out this..
– Ricky
Dec 5 at 10:48
Thank you @Morema :)
– KShewengger
Dec 5 at 14:28
add a comment |
Your Answer
StackExchange.ifUsing("editor", function () {
StackExchange.using("externalEditor", function () {
StackExchange.using("snippets", function () {
StackExchange.snippets.init();
});
});
}, "code-snippets");
StackExchange.ready(function() {
var channelOptions = {
tags: "".split(" "),
id: "1"
};
initTagRenderer("".split(" "), "".split(" "), channelOptions);
StackExchange.using("externalEditor", function() {
// Have to fire editor after snippets, if snippets enabled
if (StackExchange.settings.snippets.snippetsEnabled) {
StackExchange.using("snippets", function() {
createEditor();
});
}
else {
createEditor();
}
});
function createEditor() {
StackExchange.prepareEditor({
heartbeatType: 'answer',
convertImagesToLinks: true,
noModals: true,
showLowRepImageUploadWarning: true,
reputationToPostImages: 10,
bindNavPrevention: true,
postfix: "",
imageUploader: {
brandingHtml: "Powered by u003ca class="icon-imgur-white" href="https://imgur.com/"u003eu003c/au003e",
contentPolicyHtml: "User contributions licensed under u003ca href="https://creativecommons.org/licenses/by-sa/3.0/"u003ecc by-sa 3.0 with attribution requiredu003c/au003e u003ca href="https://stackoverflow.com/legal/content-policy"u003e(content policy)u003c/au003e",
allowUrls: true
},
onDemand: true,
discardSelector: ".discard-answer"
,immediatelyShowMarkdownHelp:true
});
}
});
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
StackExchange.ready(
function () {
StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fstackoverflow.com%2fquestions%2f53627450%2fangular-6-viewchild-is-not-working-with-lazy-loading%23new-answer', 'question_page');
}
);
Post as a guest
Required, but never shown
3 Answers
3
active
oldest
votes
3 Answers
3
active
oldest
votes
active
oldest
votes
active
oldest
votes
up vote
10
down vote
accepted
I think you are missing 'template' or 'templateUrl' in relevance to creating a Component
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 as per the user's clarification on this thread
Had added a Stackblitz Demo for your reference (Check the console)
If you want to access the ChildComponent that is rendered under the Parent Component's <router-outlet>
you can do so by utilizing (activate) supported property of router-outlet:
A router outlet will emit an activate event any time a new component is being instantiated
Angular Docs
ParentComponent's Template
@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'
}
}
The result will differ based on the visited page under your parent's children
If you visit Child1Component you will get its instance
Child1Component {title: "hi"}
If you visit Child2Component you will get its instance
Child2Component {name: "Angular"}
These results will then be reflected on your ParentComponent's onActivate(event) console for you to access
Hiii @KShewengger...thanks for your time....Actually I have multiple child components so I am useing <router-outlet></router-outlet> to render child view..
– Ricky
Dec 5 at 9:07
1
Hi @Ricky had updated my answer :) Since you can't use @ViewChild() on your ParentComponent since your ChildComponent is not a direct descendant or physically included on your Parent Component's Template. So the workaround, since you are loading them on your router-outlet, why not try to use its (activate) supported property of router-outlet
– KShewengger
Dec 5 at 9:46
1
Thanks for your answer....its too helpful for me and others also...
– Ricky
Dec 5 at 10:46
add a comment |
up vote
10
down vote
accepted
I think you are missing 'template' or 'templateUrl' in relevance to creating a Component
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 as per the user's clarification on this thread
Had added a Stackblitz Demo for your reference (Check the console)
If you want to access the ChildComponent that is rendered under the Parent Component's <router-outlet>
you can do so by utilizing (activate) supported property of router-outlet:
A router outlet will emit an activate event any time a new component is being instantiated
Angular Docs
ParentComponent's Template
@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'
}
}
The result will differ based on the visited page under your parent's children
If you visit Child1Component you will get its instance
Child1Component {title: "hi"}
If you visit Child2Component you will get its instance
Child2Component {name: "Angular"}
These results will then be reflected on your ParentComponent's onActivate(event) console for you to access
Hiii @KShewengger...thanks for your time....Actually I have multiple child components so I am useing <router-outlet></router-outlet> to render child view..
– Ricky
Dec 5 at 9:07
1
Hi @Ricky had updated my answer :) Since you can't use @ViewChild() on your ParentComponent since your ChildComponent is not a direct descendant or physically included on your Parent Component's Template. So the workaround, since you are loading them on your router-outlet, why not try to use its (activate) supported property of router-outlet
– KShewengger
Dec 5 at 9:46
1
Thanks for your answer....its too helpful for me and others also...
– Ricky
Dec 5 at 10:46
add a comment |
up vote
10
down vote
accepted
up vote
10
down vote
accepted
I think you are missing 'template' or 'templateUrl' in relevance to creating a Component
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 as per the user's clarification on this thread
Had added a Stackblitz Demo for your reference (Check the console)
If you want to access the ChildComponent that is rendered under the Parent Component's <router-outlet>
you can do so by utilizing (activate) supported property of router-outlet:
A router outlet will emit an activate event any time a new component is being instantiated
Angular Docs
ParentComponent's Template
@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'
}
}
The result will differ based on the visited page under your parent's children
If you visit Child1Component you will get its instance
Child1Component {title: "hi"}
If you visit Child2Component you will get its instance
Child2Component {name: "Angular"}
These results will then be reflected on your ParentComponent's onActivate(event) console for you to access
I think you are missing 'template' or 'templateUrl' in relevance to creating a Component
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 as per the user's clarification on this thread
Had added a Stackblitz Demo for your reference (Check the console)
If you want to access the ChildComponent that is rendered under the Parent Component's <router-outlet>
you can do so by utilizing (activate) supported property of router-outlet:
A router outlet will emit an activate event any time a new component is being instantiated
Angular Docs
ParentComponent's Template
@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'
}
}
The result will differ based on the visited page under your parent's children
If you visit Child1Component you will get its instance
Child1Component {title: "hi"}
If you visit Child2Component you will get its instance
Child2Component {name: "Angular"}
These results will then be reflected on your ParentComponent's onActivate(event) console for you to access
edited Dec 5 at 11:47
answered Dec 5 at 8:14
KShewengger
1,185412
1,185412
Hiii @KShewengger...thanks for your time....Actually I have multiple child components so I am useing <router-outlet></router-outlet> to render child view..
– Ricky
Dec 5 at 9:07
1
Hi @Ricky had updated my answer :) Since you can't use @ViewChild() on your ParentComponent since your ChildComponent is not a direct descendant or physically included on your Parent Component's Template. So the workaround, since you are loading them on your router-outlet, why not try to use its (activate) supported property of router-outlet
– KShewengger
Dec 5 at 9:46
1
Thanks for your answer....its too helpful for me and others also...
– Ricky
Dec 5 at 10:46
add a comment |
Hiii @KShewengger...thanks for your time....Actually I have multiple child components so I am useing <router-outlet></router-outlet> to render child view..
– Ricky
Dec 5 at 9:07
1
Hi @Ricky had updated my answer :) Since you can't use @ViewChild() on your ParentComponent since your ChildComponent is not a direct descendant or physically included on your Parent Component's Template. So the workaround, since you are loading them on your router-outlet, why not try to use its (activate) supported property of router-outlet
– KShewengger
Dec 5 at 9:46
1
Thanks for your answer....its too helpful for me and others also...
– Ricky
Dec 5 at 10:46
Hiii @KShewengger...thanks for your time....Actually I have multiple child components so I am useing <router-outlet></router-outlet> to render child view..
– Ricky
Dec 5 at 9:07
Hiii @KShewengger...thanks for your time....Actually I have multiple child components so I am useing <router-outlet></router-outlet> to render child view..
– Ricky
Dec 5 at 9:07
1
1
Hi @Ricky had updated my answer :) Since you can't use @ViewChild() on your ParentComponent since your ChildComponent is not a direct descendant or physically included on your Parent Component's Template. So the workaround, since you are loading them on your router-outlet, why not try to use its (activate) supported property of router-outlet
– KShewengger
Dec 5 at 9:46
Hi @Ricky had updated my answer :) Since you can't use @ViewChild() on your ParentComponent since your ChildComponent is not a direct descendant or physically included on your Parent Component's Template. So the workaround, since you are loading them on your router-outlet, why not try to use its (activate) supported property of router-outlet
– KShewengger
Dec 5 at 9:46
1
1
Thanks for your answer....its too helpful for me and others also...
– Ricky
Dec 5 at 10:46
Thanks for your answer....its too helpful for me and others also...
– Ricky
Dec 5 at 10:46
add a comment |
up vote
3
down vote
That's not how it's supposed to work. You'll be only able to get the ChildComponent
in your ParentComponent
ONLY if you have the <app-child></app-child>
tag in your ParentComponent
Template.
Something like this:
...
<app-child></app-child>
...
But since you're using child routing, and the ChildComponent
will load on the router-outlet
of your ParentComponent
you won't have access to that using ViewChild
PS: You'll only have access to it inside ngAfterViewInit
as ViewChild
can only be considered safe to have instantiated after the View has loaded:
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);
}
}
Here's a Working Sample StackBlitz for your ref that illustrates your scenario in both the cases.
PS: To get the ChildComponent
properties in your ParentComponent
, with Routing, you'll have to either use a SharedService
or you'll have to pass the ChildProperty in the route as a QueryParam and read it in your ParentComponent using the ActivatedRoute
UPDATE:
Sharing Data using Route Query Params:
Although this won't make much sense, but in your ChildComponent
, you can have a Link that would route the user to the ChildComponent with the title
property passed as a queryParam
. Something like this:
<a
[routerLink]="['/child']"
[queryParams]="{title: title}">
Go To Child Route With Query Params
</a>
And in your ParentComponent
have access to it using ActivatedRoute
like this:
...
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']);
});
...
}
...
}
Using a SharedService
Just create a SharedService
with a private
BehaviorSubject
that would be exposed as an Observable
by calling the asObservable
method on it. It's value can be set by exposing a method(setChildProperty
) that will essentially call the next
method with the updated childProperty
value :
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);
}
}
You can then inject it both in your ParentComponent
and in your ChildComponent
:
In ChildComponent
set the value:
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);
}
}
And in your ParentComponent
get the value:
...
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)
);
}
...
}
add a comment |
up vote
3
down vote
That's not how it's supposed to work. You'll be only able to get the ChildComponent
in your ParentComponent
ONLY if you have the <app-child></app-child>
tag in your ParentComponent
Template.
Something like this:
...
<app-child></app-child>
...
But since you're using child routing, and the ChildComponent
will load on the router-outlet
of your ParentComponent
you won't have access to that using ViewChild
PS: You'll only have access to it inside ngAfterViewInit
as ViewChild
can only be considered safe to have instantiated after the View has loaded:
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);
}
}
Here's a Working Sample StackBlitz for your ref that illustrates your scenario in both the cases.
PS: To get the ChildComponent
properties in your ParentComponent
, with Routing, you'll have to either use a SharedService
or you'll have to pass the ChildProperty in the route as a QueryParam and read it in your ParentComponent using the ActivatedRoute
UPDATE:
Sharing Data using Route Query Params:
Although this won't make much sense, but in your ChildComponent
, you can have a Link that would route the user to the ChildComponent with the title
property passed as a queryParam
. Something like this:
<a
[routerLink]="['/child']"
[queryParams]="{title: title}">
Go To Child Route With Query Params
</a>
And in your ParentComponent
have access to it using ActivatedRoute
like this:
...
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']);
});
...
}
...
}
Using a SharedService
Just create a SharedService
with a private
BehaviorSubject
that would be exposed as an Observable
by calling the asObservable
method on it. It's value can be set by exposing a method(setChildProperty
) that will essentially call the next
method with the updated childProperty
value :
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);
}
}
You can then inject it both in your ParentComponent
and in your ChildComponent
:
In ChildComponent
set the value:
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);
}
}
And in your ParentComponent
get the value:
...
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)
);
}
...
}
add a comment |
up vote
3
down vote
up vote
3
down vote
That's not how it's supposed to work. You'll be only able to get the ChildComponent
in your ParentComponent
ONLY if you have the <app-child></app-child>
tag in your ParentComponent
Template.
Something like this:
...
<app-child></app-child>
...
But since you're using child routing, and the ChildComponent
will load on the router-outlet
of your ParentComponent
you won't have access to that using ViewChild
PS: You'll only have access to it inside ngAfterViewInit
as ViewChild
can only be considered safe to have instantiated after the View has loaded:
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);
}
}
Here's a Working Sample StackBlitz for your ref that illustrates your scenario in both the cases.
PS: To get the ChildComponent
properties in your ParentComponent
, with Routing, you'll have to either use a SharedService
or you'll have to pass the ChildProperty in the route as a QueryParam and read it in your ParentComponent using the ActivatedRoute
UPDATE:
Sharing Data using Route Query Params:
Although this won't make much sense, but in your ChildComponent
, you can have a Link that would route the user to the ChildComponent with the title
property passed as a queryParam
. Something like this:
<a
[routerLink]="['/child']"
[queryParams]="{title: title}">
Go To Child Route With Query Params
</a>
And in your ParentComponent
have access to it using ActivatedRoute
like this:
...
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']);
});
...
}
...
}
Using a SharedService
Just create a SharedService
with a private
BehaviorSubject
that would be exposed as an Observable
by calling the asObservable
method on it. It's value can be set by exposing a method(setChildProperty
) that will essentially call the next
method with the updated childProperty
value :
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);
}
}
You can then inject it both in your ParentComponent
and in your ChildComponent
:
In ChildComponent
set the value:
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);
}
}
And in your ParentComponent
get the value:
...
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)
);
}
...
}
That's not how it's supposed to work. You'll be only able to get the ChildComponent
in your ParentComponent
ONLY if you have the <app-child></app-child>
tag in your ParentComponent
Template.
Something like this:
...
<app-child></app-child>
...
But since you're using child routing, and the ChildComponent
will load on the router-outlet
of your ParentComponent
you won't have access to that using ViewChild
PS: You'll only have access to it inside ngAfterViewInit
as ViewChild
can only be considered safe to have instantiated after the View has loaded:
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);
}
}
Here's a Working Sample StackBlitz for your ref that illustrates your scenario in both the cases.
PS: To get the ChildComponent
properties in your ParentComponent
, with Routing, you'll have to either use a SharedService
or you'll have to pass the ChildProperty in the route as a QueryParam and read it in your ParentComponent using the ActivatedRoute
UPDATE:
Sharing Data using Route Query Params:
Although this won't make much sense, but in your ChildComponent
, you can have a Link that would route the user to the ChildComponent with the title
property passed as a queryParam
. Something like this:
<a
[routerLink]="['/child']"
[queryParams]="{title: title}">
Go To Child Route With Query Params
</a>
And in your ParentComponent
have access to it using ActivatedRoute
like this:
...
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']);
});
...
}
...
}
Using a SharedService
Just create a SharedService
with a private
BehaviorSubject
that would be exposed as an Observable
by calling the asObservable
method on it. It's value can be set by exposing a method(setChildProperty
) that will essentially call the next
method with the updated childProperty
value :
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);
}
}
You can then inject it both in your ParentComponent
and in your ChildComponent
:
In ChildComponent
set the value:
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);
}
}
And in your ParentComponent
get the value:
...
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)
);
}
...
}
edited Dec 5 at 8:44
answered Dec 5 at 8:14
SiddAjmera
12.2k21137
12.2k21137
add a comment |
add a comment |
up vote
2
down vote
Make sure inside your parent.component.html
template you've added the <child></child>
tag.
Hiii @Morema...thanks for your time....Actually I have multiple child components so I am using <router-outlet></router-outlet> to render child view..
– Ricky
Dec 5 at 9:29
No worries, just trying to help and learn along the way. @KShewengger explained intelligently in his post and I also got to learn :)
– Morema
Dec 5 at 10:17
Thanks @Morema for helping me to out this..
– Ricky
Dec 5 at 10:48
Thank you @Morema :)
– KShewengger
Dec 5 at 14:28
add a comment |
up vote
2
down vote
Make sure inside your parent.component.html
template you've added the <child></child>
tag.
Hiii @Morema...thanks for your time....Actually I have multiple child components so I am using <router-outlet></router-outlet> to render child view..
– Ricky
Dec 5 at 9:29
No worries, just trying to help and learn along the way. @KShewengger explained intelligently in his post and I also got to learn :)
– Morema
Dec 5 at 10:17
Thanks @Morema for helping me to out this..
– Ricky
Dec 5 at 10:48
Thank you @Morema :)
– KShewengger
Dec 5 at 14:28
add a comment |
up vote
2
down vote
up vote
2
down vote
Make sure inside your parent.component.html
template you've added the <child></child>
tag.
Make sure inside your parent.component.html
template you've added the <child></child>
tag.
edited Dec 5 at 8:25
answered Dec 5 at 8:01
Morema
10710
10710
Hiii @Morema...thanks for your time....Actually I have multiple child components so I am using <router-outlet></router-outlet> to render child view..
– Ricky
Dec 5 at 9:29
No worries, just trying to help and learn along the way. @KShewengger explained intelligently in his post and I also got to learn :)
– Morema
Dec 5 at 10:17
Thanks @Morema for helping me to out this..
– Ricky
Dec 5 at 10:48
Thank you @Morema :)
– KShewengger
Dec 5 at 14:28
add a comment |
Hiii @Morema...thanks for your time....Actually I have multiple child components so I am using <router-outlet></router-outlet> to render child view..
– Ricky
Dec 5 at 9:29
No worries, just trying to help and learn along the way. @KShewengger explained intelligently in his post and I also got to learn :)
– Morema
Dec 5 at 10:17
Thanks @Morema for helping me to out this..
– Ricky
Dec 5 at 10:48
Thank you @Morema :)
– KShewengger
Dec 5 at 14:28
Hiii @Morema...thanks for your time....Actually I have multiple child components so I am using <router-outlet></router-outlet> to render child view..
– Ricky
Dec 5 at 9:29
Hiii @Morema...thanks for your time....Actually I have multiple child components so I am using <router-outlet></router-outlet> to render child view..
– Ricky
Dec 5 at 9:29
No worries, just trying to help and learn along the way. @KShewengger explained intelligently in his post and I also got to learn :)
– Morema
Dec 5 at 10:17
No worries, just trying to help and learn along the way. @KShewengger explained intelligently in his post and I also got to learn :)
– Morema
Dec 5 at 10:17
Thanks @Morema for helping me to out this..
– Ricky
Dec 5 at 10:48
Thanks @Morema for helping me to out this..
– Ricky
Dec 5 at 10:48
Thank you @Morema :)
– KShewengger
Dec 5 at 14:28
Thank you @Morema :)
– KShewengger
Dec 5 at 14:28
add a comment |
Thanks for contributing an answer to Stack Overflow!
- Please be sure to answer the question. Provide details and share your research!
But avoid …
- Asking for help, clarification, or responding to other answers.
- Making statements based on opinion; back them up with references or personal experience.
To learn more, see our tips on writing great answers.
Some of your past answers have not been well-received, and you're in danger of being blocked from answering.
Please pay close attention to the following guidance:
- Please be sure to answer the question. Provide details and share your research!
But avoid …
- Asking for help, clarification, or responding to other answers.
- Making statements based on opinion; back them up with references or personal experience.
To learn more, see our tips on writing great answers.
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
StackExchange.ready(
function () {
StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fstackoverflow.com%2fquestions%2f53627450%2fangular-6-viewchild-is-not-working-with-lazy-loading%23new-answer', 'question_page');
}
);
Post as a guest
Required, but never shown
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
2
can you share your parent.component.html file ?
– hana_wujira
Dec 5 at 7:48
1
Try with something like this... In your parent.component html:
<child #myChildComponent></child>
and in your parent component typescript:@ViewChild('myChildComponent') child: Child;
– Deadpool
Dec 5 at 8:19