Reputation: 4741
I would like to build a drum machine in Angular2 similar to an existing Angular project.
The way I have structured the components is to have a SequencerComponent (parent) that emits an event (@Output) at a specified interval (BPM).
// sequencer.component.ts
@Output() metronome = new EventEmitter();
onBeat(count: number) {
if(this.isPlaying) {
this.beat.one = count == 1;
this.beat.two = count == 2;
this.beat.three = count == 3;
this.beat.four = count == 4;
this.metronome.emit(this.beat);
}
}
PadsComponent (child) listens to this event (@Input) and should then play a sound if a PadComponent (grand-child) is set to active.
// pads.component.ts
export class PadsComponent {
@Input() hit: any = {};
}
// pads.component.html
<pad [class.active]="hit.one" class="column pad"></pad>
<pad [class.active]="hit.two" class="column pad"></pad>
<pad [class.active]="hit.three" class="column pad"></pad>
<pad [class.active]="hit.four" class="column pad"></pad>
I can get the classes to change but obviously I want to do more than HTML attribute binding. Working example
How can I get the child and grand-child to run a function on model change? And is there a better, more idiomatic way to solve this problem?
I have tried using ngDoCheck
but I haven't discovered how to use it in this use case.
Update: hit
is being bound to the beat
in sequencer.component.html
like so:
<!-- sequencer.component.html -->
<div class="columns">
<div class="column">
<a class="button is-success" (click)="onPlay($event)" href="">Play</a>
<a class="button is-danger" (click)="onStop($event)" href="">Stop</a>
</div>
</div>
<pads [hit]="beat"></pads>
Upvotes: 1
Views: 1407
Reputation: 16540
Instead of @Input() hit: any = {};
you can have a getter and a setter for hit
:
private _hit; // define a private variable _hit
@Input()
set hit(hit:any){
this._hit = hit; // set the private variable and do whatever you want after each change
playSomeSound(hit);
}
get hit(){
return this._hit;
}
Your template code is still the same,
<pad [class.active]="hit.one" class="column pad"></pad>
...
check this plunk for an example.
Upvotes: 2
Reputation: 28368
Here's an example of how to use ngDoCheck()
to watch for model change and emit it:
ngDoCheck() {
if (this.previousModel !== this.model) {
this.modelChange.emit(this.model);
}
this.previousModel = this.model;
}
Upvotes: 1