87

I have a directive to initializes a jQueryUI sortable on a DOM element. The jQueryUI sortable also has a set of callback events that trigger on certain actions. For example, when you start or stop sorting elements.

I'd like to pass the return parameters from such an event through the emit() function, so I can actually see what happend in my callback function. I just haven't found a way to pass parameters through an EventEmiiter.

I currently have the following.

My directive:

@Directive({
    selector: '[sortable]'
})
export class Sortable {
    @Output() stopSort = new EventEmitter();

    constructor(el: ElementRef) {
      console.log('directive');
        var options = {
          stop: (event, ui) => {
            this.stopSort.emit(); // How to pass the params event and ui...?
          }
        };

        $(el.nativeElement).sortable(options).disableSelection();
    }
}

And this is my Component that uses the event emiited by the directive:

@Component({
  selector: 'my-app',
  directives: [Sortable],
  providers: [],
  template: `
    <div>
      <h2>Event from jQueryUI to Component demo</h2>

      <ul id="sortable" sortable (stopSort)="stopSort(event, ui)">
        <li class="ui-state-default"><span class="ui-icon ui-icon-arrowthick-2-n-s"></span>Item 1</li>
        <li class="ui-state-default"><span class="ui-icon ui-icon-arrowthick-2-n-s"></span>Item 2</li>
        <li class="ui-state-default"><span class="ui-icon ui-icon-arrowthick-2-n-s"></span>Item 3</li>
      </ul>
    </div>
  `
})
export class App {
  constructor() {

  }

  stopSort(event, ui) { // How do I get the 'event' and 'ui' params here?
    console.log('STOP SORT!', event);
  }
}

How can I get the event and ui params in my stopSort() function?

Here is a demo of what I have so far: http://plnkr.co/edit/5ACcetgwWWgTsKs1kWrA?p=info

Frederik Struck-Schøning
  • 12,981
  • 8
  • 59
  • 68
Vivendi
  • 20,047
  • 25
  • 121
  • 196

4 Answers4

158

EventEmitter supports one argument, which is passed as $event to your event handler.

Wrap your parameters in an event object when you pass it to emit:

this.stopSort.emit({ event:event, ui: ui });

Then, when you handle the event, use $event:

stopSort($event) { 
  alert('event param from Component: ' +$event.event);
  alert('ui param from Component: ' + $event.ui);
}

Demo Plnkr

Frederik Struck-Schøning
  • 12,981
  • 8
  • 59
  • 68
Michael Kang
  • 52,003
  • 16
  • 103
  • 135
  • 19
    Just a small remark when using ES6 {event: event, ui: ui} can be shortened to {event, ui} – ErazerBrecht Apr 21 '17 at 09:01
  • 11
    Just a small remark since I fought with that for an hour: You HAVE TO name the property `$event` in your method. Otherwise you get an undefined. – dave0688 Nov 05 '18 at 16:08
  • 1
    Slightly off-topic but can anyone please explain about dollar($) sign? Why it's always use with EventEmiter parameter? – Sahil M. Mar 28 '21 at 17:45
34

pixelbits answer have changed a bit with final release. If you have multiple parameters, just pass it through as one object.

Child component:

this.stopSort.emit({event,ui});

@Output() stopSort= new EventEmitter<any>();

Parent Component:

hereIsHeight(value) {
        console.log("Height = " + value.event); 
        console.log("Title = " + value.ui); 
    }   

HTML in parent component:

<test-child1 (stopSort)="hereIsHeight($event)"></test-child1>

-- Also if you have values like: (with the "this" in front)

this.stopSort.emit({this.event,this.ui});

they will not work, you need to change them to something else and then pass through like:

let val1 = this.event;
let val2 = this.ui;
this.stopSort.emit({val1,val2});

*Update: Read Colin B's answer below for a way to pass values with "this."

Paul Rooney
  • 20,879
  • 9
  • 40
  • 61
Alfa Bravo
  • 1,961
  • 2
  • 25
  • 45
10

I can't add a comment, but just wanted to point out from Alpha Bravo's answer that you can pass this.event, you just can't use property value shorthand:

this.stopSort.emit({ event : this.event, ui : this.ui });

Also note, if they are passed through the EventEmmiter as this.stopSort.emit({ val1, val2 }); then they would be accessed in the parent as:

hereIsHeight(value) {
    console.log(`event = ${ value.val1 }`); 
    console.log(`ui = ${ value.val2 }`); 
}

So avoiding the shorthand might be preferable in this type of situation to keep naming consistent.

Paul Rooney
  • 20,879
  • 9
  • 40
  • 61
Colin B.
  • 126
  • 1
  • 6
5

Works like this in child:

@Output() myEvent: EventEmitter<boolean> = new EventEmitter();
myFunc(value: boolean) {
    this.myEvent.emit(value);
}

Now you just have to grab the event in the parent!

Tim
  • 5,435
  • 7
  • 42
  • 62
Ignacio Peletier
  • 2,056
  • 11
  • 24