Angular 6 @Viewchild is not working with lazy loading











up vote
6
down vote

favorite
1












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(…)









share|improve this question




















  • 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















up vote
6
down vote

favorite
1












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(…)









share|improve this question




















  • 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













up vote
6
down vote

favorite
1









up vote
6
down vote

favorite
1






1





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(…)









share|improve this question















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






share|improve this question















share|improve this question













share|improve this question




share|improve this question








edited Dec 5 at 8:07









Deadpool

350119




350119










asked Dec 5 at 7:44









Ricky

1632211




1632211








  • 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




    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












3 Answers
3






active

oldest

votes

















up vote
9
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







share|improve this answer























  • 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


















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)
);
}

...

}





share|improve this answer






























    up vote
    2
    down vote













    Make sure inside your parent.component.html template you've added the <child></child> tag.






    share|improve this answer























    • 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











    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
    });


    }
    });














    draft saved

    draft discarded


















    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
    9
    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







    share|improve this answer























    • 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















    up vote
    9
    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







    share|improve this answer























    • 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













    up vote
    9
    down vote



    accepted







    up vote
    9
    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







    share|improve this answer














    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








    share|improve this answer














    share|improve this answer



    share|improve this answer








    edited Dec 5 at 11:47

























    answered Dec 5 at 8:14









    KShewengger

    1,07839




    1,07839












    • 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






    • 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












    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)
    );
    }

    ...

    }





    share|improve this answer



























      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)
      );
      }

      ...

      }





      share|improve this answer

























        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)
        );
        }

        ...

        }





        share|improve this answer














        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)
        );
        }

        ...

        }






        share|improve this answer














        share|improve this answer



        share|improve this answer








        edited Dec 5 at 8:44

























        answered Dec 5 at 8:14









        SiddAjmera

        11.7k21137




        11.7k21137






















            up vote
            2
            down vote













            Make sure inside your parent.component.html template you've added the <child></child> tag.






            share|improve this answer























            • 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















            up vote
            2
            down vote













            Make sure inside your parent.component.html template you've added the <child></child> tag.






            share|improve this answer























            • 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













            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.






            share|improve this answer














            Make sure inside your parent.component.html template you've added the <child></child> tag.







            share|improve this answer














            share|improve this answer



            share|improve this answer








            edited Dec 5 at 8:25

























            answered Dec 5 at 8:01









            Morema

            589




            589












            • 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










            • 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


















            draft saved

            draft discarded




















































            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.




            draft saved


            draft discarded














            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





















































            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







            Popular posts from this blog

            Plaza Victoria

            Puebla de Zaragoza

            Musa