130

I'm trying to build angular2 application for production for that I'm following this blog. After my ngc successful compilation when the tsc compilation takes place it generates below error shown in the image:

After searching for a while I found this blog which explains the problem in "The context property" section which I'm not able to understood properly may be it give some good idea to you that what's happening wrong. basically when we're making a variable private we're getting "ERROR: Property is private and only accessible within class".

Stephen Ostermiller
  • 23,933
  • 14
  • 88
  • 109
Sumit Khanduri
  • 3,619
  • 7
  • 30
  • 40

10 Answers10

167

For a given component all its members (methods, properties) accessed by its template must be public in the AOT compilation scenario. This is due to the fact that a template is turned into a TS class. A generated class and a component are 2 separate classes now and you can't access private members cross-class.

In short: you can't access private members in your templates if you want to use ahead-of-time compilation.

For better explaination https://github.com/angular/angular/issues/11422

harish gadiya
  • 1,964
  • 1
  • 13
  • 9
  • 2
    but this wasnt the case earlier versions of Angular, no? i have started getting those errors after upgrading to newest version. – Emil Apr 03 '20 at 22:03
40

Maybe another even simpler answer is:

Guys, please don't call private methods, fields or properties from the HTML :)


P.S. when compiling the *.ts code to *.js, AOT refuse to connect non-public members with the HTML template.

And "yes" this will make your build pipeline to fail :D

Arsen Khachaturyan
  • 7,904
  • 4
  • 42
  • 42
  • 1
    Or access private fields/properties! – JMK Jan 24 '19 at 00:12
  • @Arsen Khachaturyan It`s funny) – voodoo417 Apr 14 '20 at 13:41
  • @JMK I've updated the post according to your suggestion, thank you. – Arsen Khachaturyan Apr 14 '20 at 13:43
  • @voodoo417, funny and true ;). Sometimes too academic answer can really blow anyone's mind, and we just need to be as simpler as we can. – Arsen Khachaturyan Apr 14 '20 at 20:05
  • 1
    @Arsen Khachaturyan Agree, Arsen+++ – voodoo417 Apr 14 '20 at 21:46
  • Yes I'm facing a build error. How to fix this thing. I'm not even calling any private method from template. Please help. – Tanzeel Feb 10 '21 at 03:37
  • 1
    @Tanzeel, the case with private/public properties can be just one of the reasons why the build is failing. The first thing to do is understand what the error message tells you. Then understand where the error is happening (what page, service, directive, etc.), or maybe it is happening for some other reason (configuration problem, etc.). After locating the problem, try to check if the above solution can be applied or not. I hope this helps. – Arsen Khachaturyan Feb 10 '21 at 06:24
29

I got this when I declared private injectables in the constructor:

constructor(private service: SpecificObjectService) { }

And used them in the template:

*ngFor="let pd of service.listSpecificObject "

The solution is:

constructor(public service: SpecificObjectService) { }
TiyebM
  • 2,684
  • 3
  • 40
  • 66
16

So I fixed this problem I'll keep this short and simple. To fix this I read this blog deeply. As in section "The context property" The solution for this problem is that Don't use or create a private variable if you want to use it in the view directly when your are creating your build with AOT (i.e., Ahead Of Time) for production.

*for Example *

// component.ts
@Component({
  selector: 'third-party',
  template: `
    {{ _initials }}
  `
})
class ThirdPartyComponent {
  private _initials: string;
  private _name: string;

  @Input()
  set name(name: string) {
    if (name) {
      this._initials = name.split(' ').map(n => n[0]).join('. ') + '.';
      this._name = name;
    }
  }
}

output: Property '_initials' is private and only accessible within class 'ThirdPartyComponent'.

Solution:

update this private _initials: string; to simply _initials: string;

For this answer Harish Gadiya provide me some help so thanx for that.

Community
  • 1
  • 1
Sumit Khanduri
  • 3,619
  • 7
  • 30
  • 40
  • dont need to use `_name` there, it can be the same as you using `this.` and other `name` its a local variable `this.name=name;` – LazerBanana Feb 21 '18 at 15:12
  • @LazerBanana, But `this.name=name` in the `set name` is inf. recursion – vp_arth Sep 12 '19 at 12:00
  • @vp_arth ? one is local one is global? even with same name 2 different things, I guess? thats why u use `this.` to point to the global one – LazerBanana Nov 29 '19 at 11:08
  • What do you mean under local/global? `name` is not variable, it is object property. `this.name = name` will trigger setter(`set name(v){}`) on that object. So easy to test it: [blitz](https://stackblitz.com/edit/typescript-zn2pm3) `Maximum call stack size exceeded` – vp_arth Nov 29 '19 at 12:06
6

This works for me guys: Simply change service to public.

constructor(public service: SpecificObjectService) { }

App working in production!!

Andronicus
  • 25,419
  • 17
  • 47
  • 88
Carlos Valdes
  • 61
  • 1
  • 1
  • 1
    So the exact same solution with a less detailed answer as @TiyebM's answer above. – Ash Jul 23 '20 at 03:44
1

If you want to use router in view, please make it public.

E.g:

<button 
   [routerLink]="['/login']"
   [queryParams]="{redirectTo: router.url}"
   translate="Please sign in to use this feature"
/>
import { Router } from '@angular/router'; 

constructor(
   public router: Router; // don't make it private
) {}

I overlooked it until Github CI sends me a warning mail.

glinda93
  • 7,659
  • 5
  • 40
  • 78
0

ok see this is really a simple javascript es6 problem, if you must keep the data type private you can simply do this

privateAccess(){
     return this.cannotAccessByInstanceButStillNeeded
}
help-info.de
  • 6,695
  • 16
  • 39
  • 41
0

You can always add a // @ts-ignore before the lines causing this error. Check Doc

Melchia
  • 22,578
  • 22
  • 103
  • 117
0

Just remove the 'private' access modifier in front of the variable. If it is the instance declared in a constructor then just change 'private' to 'public'.

0

To access private methods try to use in your tests :

spyOn(component as any, 'yourPrivateMethod').and.returnValue(...);

and

expect((component as any).yourPrivateMethod).toHaveBeenCalled();
Sergii Fasolko
  • 188
  • 1
  • 7