问题
I'm currently teaching myself Angular2 and I have a practical problem that would be easy to rectify in AngularJS but currently I'm looking through examples to find a solution with Angular2. Anyway, I have a top level component called App
and within that component I have a property that applies a css class, here is my HTML that is used as the component template - you can see where I wish to apply the css class using ngClass
. The showMenu
value is just a boolean.
<div class="navigation" role="navigation">
<ul>
<li><a [routerLink]="['Home]">Home</a></li>
<li><a [routerLink]="['Mail']">Mail</a></li>
<li><a [routerLink]="['Friends']">Friends</a></li>
<li><a [routerLink]="['Games']">Games</a></li>
</ul>
</div>
<!-- below is where I wish to toggle the class -->
<div class="site-wrap" [ngClass]="{'slide-right': showMenu}">
<div class="container-fluid">
<div class="row nav">
<top-navigation></top-navigation>
</div>
</div>
<div class="container-fluid content-gradient">
<div class="row">
<div class="col-md-10">
<router-outlet></router-outlet>
</div>
<div class="col-md-2">
<contacts-list></contacts-list>
</div>
</div>
</div>
<div class="container-fluid footer">
<footer-navigation></footer-navigation>
</div>
</div>
Here is the Component Code for App (not much to see here...)
export class App {
showMenu: boolean = false;
constructor() {
}
// I need to listen for the toggle somehow?
toggleMenu():void {
this.showMenu = !this.showMenu;
}
}
Now you can see I have a child component with the selector top-navigation
. This component TopNavigation
has a method on a button that I wish to toggle the value of showMenu
in the parent / top-level component. Here's my code so far (just small extracts)
export class TopNavigation {
constructor() {
// Things happening here
}
toggleMenu():void {
// I want to toggle the parent property by somekind of $emit
}
}
here is the template HTML (not all) for the Component.
<div class="col-xs-2 col-sm-1 hidden-md hidden-lg hamburger-menu">
<button class="btn btn-default" (click)="toggleMenu()">☰</button>
</div>
In AngularJS I would have an $scope.$emit
on the toggleMenu
function and in the parent I would have a $scope.$on
to listen for the event. I'm currently reading about EventEmitters
in Angular2 however if anyone has a quick explanation/example I would be most appreciative especially as I think this is a common / practical everyday task for Angular developers.
回答1:
I could leverage a shared service that define an EventEmitter
property. Your App
component will subscribe on it to be notified when the corresponding event is trigger by the TopNavigation
component.
Shared service
@Injectable() export class MenuService { showMenuEvent: EventEmitter = new EventEmitter(); }
Don't forget to define the corresponding provider in the boostrap function to be able to share the same instance of the service for the whole application: `bootstrap(App, [ MenuService ]);
App
component@Component({ ... }) export class App { showMenu: boolean = false; constructor(menuService: MenuService) { menuService.showMenuEvent.subscribe( (showMenu) => { this.showMenu = !this.showMenu; } ); }
}
TopNavigation
component:export class TopNavigation { constructor(private menuService: MenuService) { // Things happening here } toggleMenu():void { this.showMenu = this.showMenu; this.menuService.showMenuEvent.emit(this.showMenu); } }
See this question for more details:
- Delegation: EventEmitter or Observable in Angular2
回答2:
You can use two-way binding.
<top-navigation [(toggleMenu)]="showMenu"></top-navigation>
maybe one-way would do as well, I don't know your exact requirements
<top-navigation (toggleMenuChange)="showMenu=$event"></top-navigation>
export class TopNavigation {
@Output() toggleMenuChange: EventEmitter = new EventEmitter();
// for two-way binding
@Input() toggleMenu:boolean = false;
constructor() {
// Things happening here
}
toggleMenu():void {
this.toggleMenu = !this.toggleMenu;
this.toggleMenu.emit(this.toggleMenu);
}
}
来源:https://stackoverflow.com/questions/35719496/toggle-property-in-parent-component-from-child-component-in-angular2-similar-to