Reputation: 4614
I have a child TestComponent
component as follows:
import { Component, OnInit, Input } from '@angular/core';
import { ApiService } from '../../../api.service';
@Component({
selector: 'app-test',
templateUrl: './test.component.html'
})
export class TestComponent implements OnInit {
constructor(private apiService: ApiService) { }
testDisplayMessage = 'No data to show';
ngOnInit() {
}
getMessage(param: string) {
this.callingTest = true;
this.apiService.getTest( param ).subscribe( data => {
this.setTestDisplayMessage( data );
this.callingTest = false;
}, err => {
console.log( JSON.stringify( err ) );
this.setTestDisplayMessage( 'Failed to get data' );
this.callingTest = false;
} );
}
setTestDisplayMessage( message: string ) {
this.testDisplayMessage = message;
}
}
contents of test.component.html
<p style="padding: 10px;">{{ testDisplayMessage }}</p>
Use in parent componet :
Trigger JS Code in parent component on button click,
import { TestComponent } from './test/test.component';
....
.....
@Component({
providers: [ TestComponent ],
templateUrl: 'parent.component.html'
})
export class ParentComponent implements OnInit {
...
constructor(private testComponent: TestComponent) { }
...
// Button on parent template triggers this method
getMessage() {
this.testComponent.getMessage('Hello');
}
...
}
Html tag added in parent component,
<app-test></app-test>
When I debugged above code trigger point, call to setTestDisplayMessage()
happens the field testDisplayMessage
in TestComponent
gets changed but UI shows the old message 'No data to show'
, why is the message on change does not reflect on UI template? Or this is not the way it is supposed to get used? Shall I use @Input
Update:
Based on the pointers given in the following answers as well as comment sections, I changed my component as @ViewChild
so in above parent component instead of passing the child component as an argument to constructor I declared it as child component using @ViewChild
, so code changes as follows,
Earlier wrong code
constructor(private testComponent: TestComponent) { }
Solution
@ViewChild(TestComponent)
testComponent: TestComponent;
I found this article useful.
Upvotes: 0
Views: 1012
Reputation: 4614
Update:
Based on the pointers given in the following answers as well as comment sections, I changed my component as @ViewChild
so in above parent component instead of passing the child component as an argument to constructor I declared it as child component using @ViewChild
, so code changes as follows,
Earlier wrong code
constructor(private testComponent: TestComponent) { }
Solution
@ViewChild(TestComponent)
testComponent: TestComponent;
I found this article useful.
Upvotes: 0
Reputation: 653
basically, your approach is wrong, please use Input() or Services to share data between components.
however, if you want to make ur code work, the below may work
import change detector
constructor(private cdRef: ChangeDetectorRef) { }
note: import reference -> import { ChangeDetectorRef } from '@angular/core';
execute detect change after the value is updated
setTestDisplayMessage( message: string ) {
this.testDisplayMessage = message;
this.cdRef.detectChanges();
}
I hope this helps
Upvotes: -1
Reputation: 413
Use @ViewChild()
In html file:
<app-test #childComp></app-test>
In parent component.ts file
import { Component, OnInit, ViewChild } from '@angular/core';
....
.....
@Component( {
templateUrl: 'parent.component.html'
} )
export class ParentComponent implements OnInit {
@viewChild('childComp') childComp: any;
constructor() { }
...
// Button on parent template triggers this method
getMessage() {
this.childComp.getMessage('Hello');
}
...
}
Upvotes: 3
Reputation: 483
definitely use @Input() but on set method
@Input()
set someProperty(value) {
// do some code
}
now every time you pass new value here, code will run
Upvotes: -1