0

I can't figure out why an event is required to share from child to parent (@Output), while @Input() works fine for parent to child.

What if we want to share data with parent component without clicking any button like in case of @Input? And what if components are not related in any way?

2 Answers 2

2

Why do we need an event?

Because this prevents a circular reference. If the parent had a reference to the child and the child had a reference to the parent it would be a circular reference. It also increases the complexity of your code. If I'm writing a "button" component I don't want to have to worry about what kind of component is holding my button component.

What if we want to share data with parent component without clicking any button like in case of @Input?

You can fire off the event programmatically. For example, you could have a timer component that uses an RxJS interval observable to fire an event every 5 seconds.

interval(5000).subscribe(() => myOutput.next());

What if components are not related in any way?

Then they should communicate via a shared service and not using Input and Output.

Sign up to request clarification or add additional context in comments.

4 Comments

I disagree about the circular reference. Change detection in both directions would effectively equate to two-way binding with watches in AngularJS, which is fine. The parent would update the child, and (at worst) the change in the child would then cause change detection to fire in the parent, but nothing would further change, and then nothing else would happen.
You are correct. There would be an infinte loop in your code and it would be a flaw at runtime. This doesn't mean a circular reference is a good thing.
I don't think there would be an infinite-loop. Unless I'm mistaken, it would be equivalent to using ng-model in AngularJS.
You're right. Sorry, that second comment was supposed to say "there would NOT be an infinite loop and it would NOT be a flaw at runtime". I just can't type it seems.
0

For the first part of your question, I'd like to elaborate:

I can't figure out why you need an event to happen for sharing data from child to parent (@Output), while @Input() works fine for parent to child.

Because Angular has a uni-directional change detection system, from top to bottom.

This means changes in the parent are propagated to the child and not the other way around, by design, making the flow of application state easier to understand.

For binded properties (such as those decorated with @input) a change in value (for primitives) or reference (for objects) in the parent, will cause change detection to fire, and children will be updated with the new value or reference.

However, for example, reassigning the @input property in the child will not update the reference in the parent, as this would violate the top-down design aforementioned.

While there is a decorator for outputs, there isn't change detection from bottom to top, so changes in this direction must be explicitly told to the parent, e.g. with events, which is exactly what happens.

Further note

Despite all of this, it's still possible that changes to a binded property in a child will cause a change to be seen in the parent. This happens when an object reference is passed to the child and the child mutates the object using the reference, because, ultimately, it's still Javascript, and both parent and child have references to the same object. AND if something else causes change detection to fire in the parent, which updates the DOM and the effect of this mutation is observed on screen.

However, this code is hard to understand and debug, whereas @output is declarative and clear.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.