I am using Angular2 with Typescript
Suppose I have the following in my app component's template:
...
<coffee-cup [coffee]=""
...
My coffee-cup
component:
@Component({
selector: 'coffee-cup',
...
})
export class CoffeeCup {
@Input()
public coffee = 0;
}
I am currently unsure of what my Input should look like. It could look like this:
@Input()
public coffee = 0;
Or
@Input()
private coffee = 0;
I am currently leaning towards making the member variable coffee private.
The way that I am viewing a component is that there are two separate APIs to interact with it:
@Inputs
and @Outputs
I haven't checked what occurs in the following situation, however, it may change the answer:
appComponent
gets access to CoffeeCup
using @ViewChild
and sets the coffee member, will the lifecycle hooks (like ngOnChange
) fire?To restate the question: Should Angular2 @Input
s be public or can/should we have a stricter API by making them private?
A Question came up on StackOverflow about accessing private variables on an Angular Component class inside an Angular template. How do you do it? The short answer is you can't.
Use the @Input() decorator in a child component or directive to let Angular know that a property in that component can receive its value from its parent component. It helps to remember that the data flow is from the perspective of the child component.
@Input Decorator. @Input is a decorator to mark a property as an input. @Input is used to define an input property, to achieve component property binding. @Inoput decorator is used to pass data (property binding) from parent to child component.
First, from an API design perspective @Input
implies public. This is also true from angular perspective, these decorators describes the interface to interact with a component.
The @Input
decorator, or any other meta decorator is used by angular in a way of letting angular know about your intent and have better understanding of the template and it's relations with the component class.
It's also used, in some cases, by the change detection engine. For example, @Input
is a field tracked by the change detection, it hints to the CD engine that this property should be monitored.
Having a private property with an @Input
decorator shouldn't have any effect in runtime. This modifier is virtual and it's gone after TypeScript to JavaScript compilation.
However, there are some effects that might occur depending on your environment:
A great benefit of having TypeScript and metadata in general is having a smart IDE which means that the IDE can help you while you code. Having a private property might or might not effect that depending on the implementation of each IDE.
Having @Input
on a property will result in the IDE showing you that property on an intellisense window when you write the HTML markup for that component.
Another risk factor is future support for minification/uglification in typescript.
Private properties, as the name suggests, are used inside the class nowhere else. This trait means the complier can change the names of private properties so they take less bytes, it also makes them "more private" as the identifier might change from build to build. For example: private mySpecialProperty: string
after minification will be p1
and the compiler will change all references to this identifier in the class to match p1
.
So, having this today will work but in the future it might limit build features.
Another point to consider is that while angular does not care about modifiers your compiler does, so dynamic component creation will be limited.
In other word, creating components in html markup will work without any issues but dynamically creating components using the ComponentResolver -> ComponentFactor
will be limited since you won't be able to assign those inputs to the instance of your components using code.
If you're not planning to do so, you're good.
If you're building components to be used by others, public modifier is mandatory for
@Input/@Output
. The users of you'r component should be able to dynamically create your components.
This also answers the question about accessing these properties on a parent/child component getting reference to the coffee component. Binding will be possible via template markup only. For example, you won't be able to manually register to EventEmitter
s registered on the coffee component. This is sometimes required, see THIS scenario as one example.
As for lifecycle hooks, it should not have any effect since angular does not check the type but does an existance check.
So, to sum up, in most use cases you shouldn't have any issues but as you'r app progresses you might tackle some issues, or not. You might also have to opt-out of advanced minification features in the future...
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With