Reputation: 3671
Is it possible to conditionally bind to an output property? Something like this: <my-Component (myOutputProp)="funcThatReturnsTrueOrFalse()? func1() : func2()"></my-component>
I've tried the above example, as well as <my-Component (myOutputProp)="funcThatReturnsFunc1OrFunc2()></my-component>
.
I've looked around and come to the realization that you can't dynamically change bindings after the fact, can't access EventListeners
from nativeElement
, and seen some indications that you could do this with regular event bindings, although I couldn't get those to work either.
Thanks.
UPDATE
My output property is defined like this:
@Output() myOutputProp: EventEmitter<any> = new EventEmitter<any>();
UPDATE 2
For reasons beyond my control, I can't just fire one event and branch within that based on true/false. Primarily because in one situation, a false
value from my ternary expression evaluation will not bind anything to the output property, and I need to be able to detect that within my child component (via myOutputProp.observers.length
)
Upvotes: 0
Views: 3586
Reputation: 15180
You can use the EventEmitter
to emit based on your boolean value. Just push the appropriate value via the emit(...)
method.
Here's a simple example including two components. One component is a button, which emits a String value that changes when you click the button. The other component is consuming that event and displaying it. You can find a demo here: https://stackblitz.com/edit/angular-4natth
Here's the first component, which is a simple button. Note that clicking the button sets a boolean flag. This flag then determines which string is emitted by the event emitter.
@Component({
selector: 'my-example',
template: '<button mat-raised-button (click)="doThings()">Click me!</button>'
})
export class ExampleComponent {
@Output()
status: EventEmitter<string> = new EventEmitter();
flag = false;
doThings() {
this.flag = !this.flag; // toggle the boolean flag
this.status.emit(this.getValue()); // push the value
}
private getValue() {
if(this.flag) {
return "Truthy!";
}
return "Falsy!";
}
}
The second component is consuming and the values being emitted from (status)
:
@Component({
selector: 'my-container',
template: '<my-example (status)="updateStatus($event)">loading...</my-example><p>Current status: {{status}}</p>'
})
export class ContainerComponent {
status: string = "Not set yet - click the button!";
updateStatus(value: string) {
this.status = value;
}
}
Whenever you click the button, the EventEmitter.emit(...)
method is called, pushing the appropriate value. On the other end, the event is consumed using (status)="updateStatus($event)"
, where in this case $event
is of type string because I've declared the EventEmitter to be emitting a string. I could easily have also been emitting a boolean value and have the updateStatus
method instead do different things based on the emitted value.
So, say for example you have this in your Component:
@Output()
myOutputProp: EventEmitter<boolean> = new EventEmitter();
You could then do something like this:
<my-Component (myOutputProp)="someFunc($event)"></my-component>
And define your someFunc
like this:
someFunc(emittedValue: boolean) {
emittedValue ? func1() : func2();
}
Or, let's say you need the output of your event emitter to be some sort of value that you need preserved rather than a boolean. You could still declare your component the same:
<my-Component (myOutputProp)="someFunc($event)"></my-component>
And define your someFunc
like this:
someFunc(emittedValue: any) {
funcThatReturnsTrueOrFalse() ? func1(emittedValue) : func2(emittedValue);
}
So while you can't directly bind the ternary to the event emitter, you can instead bind something static which turns around and invokes the ternary itself.
Upvotes: 2