While going through the tutorial, i am coming across a strange scenario.
while injecting the service in your component if you miss the access modifier it will give you error as given below, but adding it as private or public will run fine.
Dont we have any default scope in Angular if we miss the access modifier ?
export class UserDetailsComponent implements OnInit {
name="";
lastName="";
constructor(userService : UserServiceService) { }
ngOnInit() {
}
save(){
this.userService.saveUser();
}
}
Property 'userService' does not exist on type 'UserDetailsComponent'.
If you prefix a constructor parameter with an access modifier (private
, protected
or public
) or readonly
, it automatically gets "promoted" to be a class property in TypeScript. This construct is referred to as constructor parameter properties.
Without the prefix, the constructor parameter is nothing more than a method parameter, and you would have to manually assign it to a declared class property from the constructor itself.
From the handbook:
Parameter properties are declared by prefixing a constructor parameter
with an accessibility modifier or readonly
, or both. Using private
for a parameter property declares and initializes a private member;
likewise, the same is done for public
, protected
, and readonly
.
All of the answers already provided are very clear and have good info. So to put things in a simple way, here is what is happening:
Your constructor is a function. In any programming language (that I've come across so far) a function's parameters only exist within the scope of the function itself. So the parameter being passed in the constructor is not available throughout the class unless its value is explicitly assigned to a class member (as seen in the second piece of code provided by Samuel J Matthew.
What the access modifiers in the parameter do is they instruct Angular to create a class member of the same name as the parameter, with the provided access modifier, and initialize it to an instance of the parameter type. In other words, the parameter becomes a class member/property. As has already been said, this is called a parameter property, which is a very fitting name for it.
The documentation provided by Ken is very helpful. Definitely worth reading.
Typescript provides a shortcut for you for a common pattern for dependency injection.
You can either put this in your constructor:
this.userService = userService
And also create a property declaration:
userService: UserService;
Or, you can just put ‘public’ on the ctor function parameter and Typescript does all that for you. The same works for ‘private’. But AOT may fail if try to use a private property in your template.
More info
The problem occurs when you are not providing any access specifier for the parameters of constructor it will not get registered at class level.Instead the scope of the parameter variable limited to the constructor function.In order to make it available across the class we give the access modifiers
With your example
export class UserDetailsComponent implements OnInit {
name="";
lastName="";
constructor(userService : UserServiceService) {
console.log(userService)
}
ngOnInit() {
}
save(){
this.userService.saveUser();
}
}
the userService
is only available inside constructor
If you place a console.log(userService)
inside constructor you may get some console output.
If you don't want to specify any access modifiers or want to assign to a another class variable you can specify like following
export class UserDetailsComponent implements OnInit {
name="";
lastName="";
private _service
constructor(userService : UserServiceService) {
this._service = userService;
}
ngOnInit() {
}
save(){
this._service.saveUser();
}
}
In the above code i had assigned the injected userService
to another class member _service