In the root component of the route configuration I have a button. When I click this button, I would like to trigger an event inside the activated child route.
I have been struggling with this for a while now, and the only thing that seems promising is using a bi-directional service (link to angular docs). However, I'm not sure how to get it working.
Here is a plunk to demonstrate:
https://plnkr.co/edit/7zDTTTlABWD2GFo01jaz?p=preview
I've set up a simple route configuration which automatically redirects to the TestComponent. When I click on the 'click' button at the route app level, I would like to be able to trigger the clickDetected()
function inside TestComponent.
Hope everything is clear - any advice is appreciated!
Code below;
app.component
@Component({
selector: 'my-app',
template: `
<input type="button" (click)="onClick('hello')" value="click" />
<router-outlet></router-outlet>
`,
})
export class AppComponent {
constructor(private testService: TestService) {
}
onClick(v){
this.testService.declareClick(v)
}
}
test.service
@Injectable()
export class TestService {
private clickedSource = new Subject<string>();
clicked$ = this.clickedSource.asObservable();
declareClick(value: string) {
console.log(value)
return this.clickedSource.next(value);
}
}
test.component
@Component({
selector: 'my-test',
template: `
<div>
<h1>Test Component</h1>
</div>
`,
})
export class TestComponent implements OnInit {
public clicked?: any
constructor(private testService: TestService) {
}
clickDetected(){
console.log("parent clicked")
}
ngOnInit(){
this.testService.declareClick()
/* .subscribe((v) => {
this.clicked? = v;
console.log(v)
})*/
}
}
@Input() and @Output() give a child component a way to communicate with its parent component. @Input() lets a parent component update data in the child component. Conversely, @Output() lets the child send data to a parent component.
To call a parent component method from the child component, we need to pass the changeName() method as a prop to the child component and access it as a props data inside the child component.
EDIT -- DO NOT DO THIS --
Thanks to @echonax, I learned that is actually an example of what you should NOT do. I came to actually help people and I ended up learning something. Please, refer to the angular2 doc on why you should NOT do this.
END EDIT
You can also do this using a Shared Module. You make a module that provide the test service and import both in AppModule and your routed module. You can then provide the same instance of the service to both component. I made you a plunkr from your code that show how it works.
If you want more information on SharedModule, check Angular2 doc. https://angular.io/docs/ts/latest/guide/ngmodule.html#!#shared-module
Edited your question plunkr. https://plnkr.co/edit/SU8AT4
Shared Module
import { NgModule } from '@angular/core';
import { TestService } from './test.service';
@NgModule({
imports: [],
declarations: [],
providers: [
TestService
],
exports: [ ]
})
export class SharedModule { }
New AppModule
import { NgModule } from '@angular/core';
import { BrowserModule } from '@angular/platform-browser';
import { AppComponent } from './app.component';
import { TestComponent } from './test.component';
import { SharedModule } from './shared.module';
import { AppRoutingModule } from './app-routing.module';
@NgModule({
imports: [
BrowserModule,
AppRoutingModule,
SharedModule
],
declarations: [
AppComponent,
TestComponent
],
providers: [ ],
bootstrap: [ AppComponent ]
})
export class AppModule { }
New AppRoutingModule
import { NgModule } from '@angular/core';
import { RouterModule, Routes } from '@angular/router';
import { TestComponent } from './test.component';
import { SharedModule } from './shared.module';
const appRoutes: Routes = [
{ path: '', redirectTo: 'test', pathMatch: 'full' },
{ path: 'test', component: TestComponent },
];
@NgModule({
imports: [
RouterModule.forRoot(appRoutes),
SharedModule
],
exports: [ RouterModule ],
providers: []
})
export class AppRoutingModule { }
You just need to .subscribe()
to the Observable
that is receiving the .next()
events:
this.testService.clickedSource.subscribe((val)=>{
console.log(2, val);
});
Fixed Plunker: https://plnkr.co/edit/aPR6KvuOi2tgQXLgokHi?p=preview
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With