My parent component receives an id value from a route parameter and I need to pass this value to a child component using the Input()
decorator. The issue I'm facing is that I can't seem to get the route param value to be passed to the child component dynamically. When I hard-code a value and pass it, everything works fine which leads me to believe that the binding and child component logic are correct; the problem seems to lie in how or where I'm setting the value dynamically.
Below is the complete parent component with some explanatory comments:
import { Component } from '@angular/core';
import { HTTP_PROVIDERS } from '@angular/http';
import { provide } from '@angular/core';
import { Routes, Router, RouterUrlSerializer, ROUTER_DIRECTIVES } from '@angular/router';
import { Location } from '@angular/common';
import { XHRBackend } from '@angular/http';
import { ContentNode } from './content-node';
import { ContentTreeComponent } from './content-tree.component';
import { ContentDashboardComponent } from './content-dashboard.component';
import { ContentEditComponent } from './content-edit.component';
import { ContentService } from '../services/content.service';
import { InitService } from '../services/init.service';
import { RouteNames } from '../services/route-names.service';
@Component({
selector: 'my-dashboard',
template: `
<div class="tree-panel-container">
<div class="tree-panel-content">
<content-tree [startNodeId]="startNodeIdContent" [currentNodeId]="currentNodeId"></content-tree>
</div>
</div>
<router-outlet></router-outlet>
`,
directives: [
ContentTreeComponent,
ContentDashboardComponent,
ROUTER_DIRECTIVES
],
providers: [
HTTP_PROVIDERS
]
})
@Routes([
{ path:'/', component: ContentDashboardComponent },
{ path:'/:id', component: ContentEditComponent }
])
export class ContentComponent {
_currentNodeId: number;
constructor(private router:Router, private routeSerializer:RouterUrlSerializer, private location:Location) {
router.changes.first().subscribe(() => {
let urlTree = this.routeSerializer.parse(location.path());
let urlSegment = urlTree.children(urlTree.children(urlTree.root)[0])[0];
if(urlSegment != undefined){
let id = urlSegment.segment;
this._currentNodeId = id;
console.log('_currentNodeId', this._currentNodeId); // This works - it logs the correct id from the route param
}
});
}
startNodeIdContent = InitService.startNodeIdContent;
currentNodeId = this._currentNodeId; // This doesn't work - it just results in 'undefined' in the child component
// The following line works; it passes 123 to the child component, so I know the binding and the child input is set up correctly:
// currentNodeId = 123;
}
...and here's the child component:
import { Component, Input, OnInit } from '@angular/core';
import { Router, RouteSegment, RouteTree } from '@angular/router';
import { ContentNode } from './content-node';
import { ContentService } from '../services/content.service';
@Component({
selector: 'content-tree',
directives: [ContentTreeComponent],
template: `
<ol class="tree">
<li *ngFor="let contentNode of contentNodes" class="tree__branch" [ngClass]="{'tree__branch--has-children': contentNode.HasChildren}">
<a *ngIf="contentNode.HasChildren" (click)="contentNode.toggle=!contentNode.toggle" class="tree__branch__toggle">
{{ !!contentNode.toggle ? '-' : '+' }}
</a>
<a class="tree__branch__link" (click)="onSelect(contentNode)">{{ contentNode.Name }}</a>
<content-tree *ngIf="contentNode.toggle" [startNodeId]="contentNode.Id"></content-tree>
</li>
</ol>
<div class="error" *ngIf="errorMessage">{{errorMessage}}</div>
<p>{{test}}</p>
`
})
export class ContentTreeComponent implements OnInit {
constructor(
private _contentService: ContentService,
private _router: Router,
private _currSegment: RouteSegment
) { }
errorMessage: string;
@Input('startNodeId')
private _startNodeId: number;
@Input('currentNodeId')
private _currentNodeId: number;
contentNodes: ContentNode[];
ngOnInit() {
this.getContentNodes();
console.log('_startNodeId = ' + this._startNodeId);
console.log('_currentNodeId = ' + this._currentNodeId);
}
onSelect(contentNode: ContentNode) {
this._router.navigate([`./${contentNode.Id}`], this._currSegment);
}
getContentNodes() {
this._contentService.getContentNodes(this._startNodeId)
.subscribe(
contentNodes => this.contentNodes = contentNodes,
error => this.errorMessage = <any>error
);
}
}