RVP
RVP

Reputation: 2400

Angular2 router - accessing parent component variables from inside a child component

I have the following module routing setup

const personsRoutes: Routes = [
{ 
    path: '',
    redirectTo: '/persons',
    pathMatch: 'full'
},
{ 
    path: 'persons', 
    component: PersonsComponent,

    children: [
        {
            path: '',
            component: PersonListComponent
        },
        {
            path: ':id',
            component: PersonDetailComponent,

            children: [
                {
                    path: '',
                    redirectTo: 'info',
                    pathMatch: 'full'
                },
                {
                    path: 'info',
                    component: PersonDetailInfoComponent,
                },
                {
                    path: 'edit',
                    component: PersonDetailEditComponent,
                },
                {
                    path: 'cashflow',
                    component: PersonDetailCashflowComponent,
                }
            ]
        }
    ]
}
];

So when I try to open up http://localhost:4200/persons/3/edit Angular2 would first load PersonsComponent followed by PersonDetailComponent followed by PersonDetailInfoComponent.

Now in PersonDetailComponent I have a service request to retrieve the person info from the backend and I would like to use the retrieved Person information inside the PersonDetailInfoComponent as well.

So my question is whether Angular2 provides an inbuilt way where I can access variables from the parent components (ex: access PersonDetailComponent.personModelfrom inside PersonDetailInfoComponent).

Is there an Angular-endorsed "right" way of doing this or is it one of those things where everyone will end up implementing their own custom solution? Also, in case this is not readily available, are there any plans to provide this functionality down the road in a later version of Angular2?

Cheers and thank in advance.

P.S.

My dependencies/versions are as follows:

"@angular/common": "2.0.0",
"@angular/compiler": "2.0.0",
"@angular/core": "2.0.0",
"@angular/forms": "2.0.0",
"@angular/http": "2.0.0",
"@angular/platform-browser": "2.0.0",
"@angular/platform-browser-dynamic": "2.0.0",
"@angular/router": "3.0.0",
"core-js": "^2.4.1",
"rxjs": "5.0.0-beta.12",
"ts-helpers": "^1.1.1",
"zone.js": "^0.6.23"

Upvotes: 0

Views: 2015

Answers (1)

RVP
RVP

Reputation: 2400

Ok so after nobody replied and after I went through the docs and API and found nothing this is what I ended up doing:

Created a data service

import { Injectable } from '@angular/core';

import { PersonModel } from '../models/person/person.model';

@Injectable()
export class DataService {

    private _person: PersonModel;

    get person(): PersonModel {
        return this._person;
    }

    set person(person: PersonModel) {
        this._person = person;
    }

    constructor() { }

}

Then in my parent route component (PersonDetailComponent) I add a provider for DataService, I inject it in the constructor and update the dataservice.person object every time we get the latest person object from the service.

@Component({
    selector: 'person-detail',
    templateUrl: './person-detail.component.html',
    styleUrls: ['./person-detail.component.scss'],
    providers: [DataService]
})
export class PersonDetailComponent implements OnInit {

    private _sub: Subscription;
    public _person: PersonModel;

    constructor(private _route: ActivatedRoute, private _router: Router, private _service: PersonService, private _ds: DataService) { }

    ngOnInit() {
        console.log("Loaded person detail component");
        this._sub = this._route.params.subscribe(params => {
             let id = +params['id']; // (+) converts string 'id' to a number
             this._service.get(id).subscribe(person => {
                console.log(`Loaded person`, person);
                this._person = person;
                this._ds.person = person;
             });
        });
    }
}

Then in my child route component (PersonDetailEditComponent) I inject the data service and I just get the person from there.

@Component({
    selector: 'person-detail-edit',
    templateUrl: './person-detail-edit.component.html',
    styleUrls: ['./person-detail-edit.component.scss']
})
export class PersonDetailEditComponent implements OnInit {

    constructor(private _ds: DataService) { }

    ngOnInit() {
        console.log('Loaded person-edit view for', this._ds.person);
    }

}

Of course the data service can be done a lot cleaner with subjects/observables/subscribers but I just wanted to share the general approach.

Hope this helps someone down the road.

Upvotes: 1

Related Questions