Właściwość „X” jest prywatna i dostępna tylko w klasie „xyzComponent”

102

Próbuję zbudować aplikację angular2 do produkcji, śledzę tego bloga . Po udanej kompilacji ngc, gdy ma miejsce kompilacja tsc , generuje poniższy błąd pokazany na obrazku:

wprowadź opis obrazu tutaj

Po dłuższych poszukiwaniach znalazłem tego bloga, który wyjaśnia problem w sekcji „Właściwość kontekstu”, którego nie jestem w stanie poprawnie zrozumieć, może to dobry pomysł, że to co się dzieje nie tak. w zasadzie kiedy ustawiamy zmienną jako prywatną, otrzymujemy "BŁĄD: Właściwość jest prywatna i dostępna tylko w klasie" . Nie rozumiem, dlaczego to nadchodzi.

Prosimy o pomoc, bo przez ostatnie kilka dni waliliśmy się w głowę z tym problemem.

Sumit Khanduri
źródło
1
czy próbowałeś zmienić właściwość z prywatnej na publiczną?
Xin Meng
czy możesz udostępnić zawartość pliku ts, która powoduje błąd?
Raj

Odpowiedzi:

143

Dla danego składnika wszystkie jego elementy członkowskie (metody, właściwości), do których ma dostęp jego szablon, muszą być publiczne w scenariuszu kompilacji AOT. Wynika to z faktu, że szablon jest przekształcany w klasę TS. Wygenerowana klasa i komponent są teraz dwiema oddzielnymi klasami i nie możesz uzyskać dostępu do prywatnych elementów członkowskich między klasami.

Krótko mówiąc: nie możesz uzyskać dostępu do prywatnych członków w swoich szablonach, jeśli chcesz użyć kompilacji z wyprzedzeniem.

Dla lepszego wyjaśnienia https://github.com/angular/angular/issues/11422

harish gadiya
źródło
ale tak nie było we wcześniejszych wersjach Angulara, prawda? Zacząłem otrzymywać te błędy po aktualizacji do najnowszej wersji.
Emil
37

Być może inną, jeszcze prostszą odpowiedzią jest:

Chłopaki, nie wywołujcie prywatnych metod, pól ani właściwości z HTML :)


PS podczas kompilowania *.tskodu do *.js, AOT odmawia połączenia niepublicznych członków z szablonem HTML .

I "tak", to spowoduje, że potok kompilacji zawiedzie: D

Arsen Khachaturyan
źródło
1
Lub uzyskaj dostęp do prywatnych pól / właściwości!
JMK
@Arsen Khachaturyan To zabawne)
voodoo417
@JMK Zaktualizowałem post zgodnie z twoją sugestią, dziękuję.
Arsen Khachaturyan
@ voodoo417, zabawne i prawdziwe;). Czasami zbyt akademicka odpowiedź może naprawdę zaskoczyć każdego i po prostu musimy być tak prostsi, jak to tylko możliwe.
Arsen Khachaturyan
1
@Arsen Khachaturyan Zgadzam się, Arsen +++
voodoo417
17

Otrzymałem to, gdy zadeklarowałem prywatne iniekcje w konstruktorze:

constructor(private service: SpecificObjectService) { }

I użyłem ich w szablonie:

*ngFor="let pd of service.listSpecificObject "

Rozwiązaniem jest:

constructor(public service: SpecificObjectService) { }
TiyebM
źródło
16

Więc naprawiłem ten problem, pozostawiam to krótkie i proste. Aby to naprawić, głęboko przeczytałem tego bloga . Jak w sekcji „ Właściwość kontekstu ” Rozwiązanie tego problemu polega na tym, że nie używaj ani nie twórz zmiennej prywatnej, jeśli chcesz jej używać bezpośrednio w widoku podczas tworzenia kompilacji z AOT ( tj. Ahead Of Time ) dla produkcja.

*na przykład *

// 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;
    }
  }
}

dane wyjściowe: Właściwość „_initials” jest prywatna i dostępna tylko w klasie „ThirdPartyComponent”.

Rozwiązanie:

zaktualizuj to private _initials: string;po prostu_initials: string;

W tej odpowiedzi Harish Gadiya zapewni mi pomoc, a dzięki temu.

Sumit Khanduri
źródło
nie trzeba go _nametam używać , może być taki sam, jak używany, this.a inna namejego zmienna lokalnathis.name=name;
LazerBanana.
@LazerBanana, ale this.name=namew set namejest inf. rekurencja
vp_arth
@vp_arth? jeden jest lokalny, jeden jest globalny? nawet z tą samą nazwą 2 różne rzeczy, jak sądzę? dlatego this.
zwykłeś
Co masz na myśli, mówiąc lokalnie / globalnie? namenie jest zmienną, jest własnością obiektu. this.name = namewywoła setter ( set name(v){}) na tym obiekcie. Tak łatwo to przetestować: blitz Maximum call stack size exceeded
vp_arth
6

Dla mnie to działa: po prostu zmień usługę na publiczną.

constructor(public service: SpecificObjectService) { }

Aplikacja działa w produkcji !!

Carlos Valdes
źródło
Czyli dokładnie to samo rozwiązanie z mniej szczegółową odpowiedzią, jak odpowiedź @ TiyebM powyżej.
Ash
1

ok zobacz, to naprawdę prosty problem z javascriptem es6, jeśli musisz zachować prywatność typu danych, możesz po prostu to zrobić

privateAccess(){
     return this.cannotAccessByInstanceButStillNeeded
}
MIchael Odumosu
źródło
0

Jeśli chcesz używać routera w widoku, upublicznij go.

Na przykład:

<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
) {}

Przeoczyłem to, dopóki Github CI nie wyśle ​​mi ostrzeżenia.

bravemaster
źródło