Reputation: 10751
The problem is that the property which is passed to the view child becomes undefined
:
Parent component:
@Component({
selector: 'app-searchbox',
template: `
<app-artifact-list [artifacts]="searchResults"></app-artifact-list>
`
})
export class SearchboxComponent implements OnInit {
// explicitly initialize the property
// the same effect with constructor initialization
searchResults: Artifact[] = [new Artifact()];
constructor(private artifactService: ArtifactService) {
}
ngOnInit(): void {
this.pollService(this.artifactService.findByQuery('guice'));
}
private pollService(request: Observable<Artifact[]>) {
return request.subscribe(this.fillInResults);
}
private fillInResults(result: Artifact[]) {
result.forEach(console.log);
for (let obj of result) {
// this.searchResults is undefined! why?
this.searchResults.push(obj);
}
}
}
Child component:
@Component({
selector: 'app-artifact-list',
template: `
<h1>{{_artifacts | json}}</h1>
`
})
export class ArtifactListComponent implements OnChanges {
private _artifacts: Artifact[] = [];
ngOnChanges(changes: SimpleChanges): void {
console.log('Property changed');
}
@Input()
set artifacts(artifacts: Artifact[]) {
console.error('Property changed');
this._artifacts = artifacts;
}
}
During constructor call I see that the property is properly initialized but in the callback method it becomes undefined
.
Isn't it somehow related to this
? Maybe this.searchResults
refers to anything else in the callback?
Upvotes: 2
Views: 191
Reputation: 10751
After some investigation into this
when it is used in scope of "function references", I found out that actually this
refers to another object. I love javascript :)
So the workaround is:
private pollService(request: Observable<Artifact[]>) {
return request.subscribe(
this.fillInResults.bind(this)
);
}
private fillInResults(result: any) {
result.forEach(console.log);
for (let obj of result) {
this.searchResults.push(obj);
}
}
Or to use fat arrow function:
private pollService(request: Observable<Artifact[]>) {
return request.subscribe(
result => this.fillInResults(result)
);
}
private fillInResults(result: any) {
result.forEach(console.log);
for (let obj of result) {
this.searchResults.push(obj);
}
}
See this question for detailed explanation: Angular2 component's “this” is undefined when executing callback function
Upvotes: 3