How to call @Input EventEmitter from parent in Angular 2

16,009

Solution 1

If you child component has:

@Input x(): number;

Then you are being asked to pass a value from the parent to the child component as so:

<my-component [x]="myVariable"></my-component>

Where 'myVariable' represents a variable that is of type 'number'. In your case, your input is named 'inputEvents' and is of type 'EventEmitter<{ type: string, data: string | DateModel }>'. So from you parent component, you would pass in the input just the same.

<ng2-datepicker [(ngModel)]="myDate" [inputEvents]='toggleCalEvent'></ng2-datepicker>

Where variable 'toggleCalEvent' is of type 'EventEmitter<{ type: string, data: string | DateModel }>', as so on your parent component:

private toggleCalEvent: EventEmitter<{ type: string, data: string | DateModel }> = new EventEmitter();

Then you could call on this EventEmitter like any EventEmitter:

openCal() {
     this.toggleCalEvent.next({ type: 'action', data: 'toggle' });
}

Since the datepicker is subscribed to this 'inputEvents', then when you trigger a 'next', it will trigger this event in the child. But there is still one issue. If you are triggering this event on a click of something, it will not work. Try this:

<div 
    (click)='openCal()' 
    (mouseenter)='openCal()'
    style='background-color:yellow; width:100px; height:50px;'
></div>
<ng2-datepicker [(ngModel)]="myDate" [inputEvents]='toggleCalEvent'></ng2-datepicker>

You will see that the calendar toggles on mouseenter but not click. This is because the datepicker is scripted to close if you click anywhere outside the calendar. So it opens and closes immediately on click of the div. To prevent this, you can add this to prevent the click from bubbling up:

<div 
    (click)='openCal($event)' 
    (mouseenter)='openCal($event)'
    style='background-color:yellow; width:100px; height:50px;'
></div>
<ng2-datepicker [(ngModel)]="myDate" [inputEvents]='toggleCalEvent'></ng2-datepicker>

openCal(e) {
    this.toggleCalEvent.next({ type: 'action', data: 'toggle' });
    e.preventDefault();
    e.stopImmediatePropagation();
}

Now the calendar show toggle as expected.

Solution 2

Angular suggests to use the ngOnChange() event for that:

OnChanges
Angular calls its ngOnChanges method whenever it detects changes to input properties of the component (or directive). This example monitors the OnChanges hook.The ngOnChanges method takes an object that maps each changed property name to a SimpleChange object holding the current and previous property values.

https://angular.io/docs/ts/latest/guide/lifecycle-hooks.html#!#onchanges

So in your case, you could just "subscribe", like this:

export class MyComponent implements OnChanges {

    @Input('parentSelection') private parentSelection;

    ngOnChanges(changes: SimpleChanges) {

        let newVal = changes['parentSelection'].currentValue;


        console.log('parent changed value to: ' + newVal);

        this.someFunction();
    }

    // depending on your needs you could also do *ngIf toggles in the template
    private someFunction() {

        switch (this.parentSelection) {

            case 'toggle':
                this.toggle();
                break;

            case 'open':
                this.open();
                break;

            case 'close':
                this.close();
                break;

            default:
                console.log("unknown event detected: " + this.childValue);
                break;
        }

    }

}
Share:
16,009
Vanquiza
Author by

Vanquiza

Updated on July 23, 2022

Comments

  • Vanquiza
    Vanquiza almost 2 years

    Hi I have a child component with the following @input:

    @Input() inputEvents: EventEmitter<{ type: string, data: string | DateModel }>;
    
    this.inputEvents.subscribe((e: any) => {
            if (e.type === 'action') {
              if (e.data === 'toggle') {
                this.toggle();
              }
              if (e.data === 'close') {
                this.close();
              }
              if (e.data === 'open') {
                this.open();
              }
            }
    }
    

    How do I trigger the subscribe from the parent? I have tried the following in the parent component but it does not work:

    @Output() datePickerAction: EventEmitter<{ type: string, data: string }>;
    
    this.datePickerAction.next({ type: 'action', data: 'toggle' });