I got this function in my core
component:
isValid(value: any) {
// Do some stuff and return something based on the result
return false;
}
Which I pass to the other-component
like this:
<other-component (onBeforeAdding)="isValid($event)"></other-component>
And in other-component
I got this EventEmitter
function which should run before other things and return a value stating that a value is valid or not:
@Output() onBeforeAdding: EventEmitter<any> = new EventEmitter();
let isValid = this.onBeforeAdding.emit(value) || true;
if (isValid) {
// Do stuff
}
The problem here is that an EventEmitter
function can't return a value since it's asynchronous (although from rc2 it seems that this is optional by passing true to the new EventEmitter
function? Even doing so won't fix this issue however). So isValid
will always be true regardless of what the function returns.
How can I return a value from the EventEmitter
function?
The short answer is you can't do this with @Output
, but you can do something very similar with @Input
.
Same function in core
component:
isValid(value: any): boolean {
// Do some stuff and return something based on the result
return false;
}
Pass the function definition in to other-component
as an @Input
:
<other-component [onBeforeAddingProcessor]="isValid"></other-component>
In other-component
:
@Input() onBeforeAddingProcessor: (value: any) => boolean;
ngOnInit() {
// onBeforeAddingProcessor won't be defined in the constructor
let isValid = this.onBeforeAddingProcessor(value);
if (isValid) {
// Do stuff
}
}
Methods accessing this
If you have to access this
in the function you provide, then it's necessary to pass a method which already has the this-context bound:
isValid = (value: any) => {
return this.myService.checkValue(value);
}
Otherwise Angular calls the method with this
of the component, not the consumer of the component.
Small hint regarding performance (though not tested): if this method is large and the instance-count of the component is high, then you should factor out the bigger parts of the code to a private member function and call this function from where it was factored out. Reason: Above does not create a function on the prototype of the class, but stamps out a copy of this function for each instance of the component. This can consume a lot of memory which can be avoided easily.
You need to subscribe on the event emitter to get the value:
this.onBeforeAdding.emit(value || true);
this.onBeforeAdding.subscribe(isValid => {
if (isValid) {
// Do stuff
}
});
The emit function send a broadcast signal to all listeners passing the value that you determined. I think the isValid logic needs to emit the event, because the responsibillity of EventEmitter is emit events and not validate things.
How exactly do you want to write this isValid flow?
I'd suggest you build a small example.
But here is how I understand your question.
I think you should use another property with EventEmitter because you are trying to get the return of isValid() from core component and EventEmitter is only a one way street.
So I would create a observable variable and assign to other-component, so it can subscribe to it. When isValid() executed, use next
to publish a new value.
An simple example is like you can subscribe to valueChanges from a form control.
@Isaac 's answer is using @input but if you wanna use observable for this, my solution will fit better.