My coworker, Charlie Koster, and I had a … disagreement? over a particular component. It left me with a bit of an existential crisis as I drove home. I’ve touted the concept of smart vs dumb components in the past, but now I’m wondering: is there such thing as a purely presentational component in Angular?
A TL;DR to the above question is yes, but it’s not going to be a useful component.
The conclusion I came to on the drive home is that there does not exist an Angular component, with bindings, that is completely stateless. Do you have a @ binding? There’s now a property on your controller that represents the state of that component. Do you have a one way binding? Yup, you now have a new stateful property on your controller. If you follow best practices and create a deeply cloned copy of that collection, it’s even more apparent that you have an internal state.
Now, you may not act upon that state or modify it in any fashion, but there is still a series of properties that exist purely on a component controller which represents the state of the component. Even though those properties are provided by the parent, which ultimately maintains the values, you can disconnect from the changes made by the parent with one time bindings. This, to me, highlights that the component does, in fact, have a state; one that can be dynamically updated by the parent.
The one use case I could think of where a component is a pure presentational component is one that has no ng-models & no bindings. These types of components are extremely rare in Angular applications, as the use case for non-dynamic components is one I rarely have encountered. One could argue that even callback bindings are a sort of state since what is passed to the controller isn’t that of the parent’s function callback, but an Angular wrapped function.
This was all driven by a component that incremented or decremented an input value with a plus or minus button. My thought was that the incrementing or decrementing of the value should be done by the component’s controller, and the parent could choose to act upon that change or not. How it was implemented was that the parent was notified that the user changed the input. There were 3 events that could trigger this change: manual modification of the text field, pressing the +, or pressing the -. This was notified by sending the value entered, the original value plus 1, or the original value minus 1.
Our disagreement ultimately boiled down to a difference of view on whether or not the component was a purely presentational component. Charlie Koster’s argument was that to remain a presentational component, the changes should be set to the property bound via the value one way binding back into the component. This follows the pure presentational component theory, because the parent maintains the state of the value. However, it has to parse the integer value from the view. Why would it have to parse an integer, when it was given an integer? Internal state!
If it was to be purely presentational, I’m not sure that it could possibly have an input field, or the parent would have to decide how to act upon a user modifying the input field, at a minimum.
There is more thoughts to be had on this matter…but I’m trying to think of this as academically as I can.
Let me know what you think! Can there be a presentational Angular component that has bindings?