Sprawdź, czy wyjście jest obecne na komponencie

14

Rozważ następujący komponent:

@Component({
  selector: 'app-test'
  template: 'Hello!'
}}
export class TestComponent {
  @Output() readonly selectionChange = new EventEmitter<SomeTypeHere>();
}

Z rozmową:

<app-test (selectedChange)="selectedChangeHandler($event)"></app-test>

Zauważ, że napisałem selectedChangezamiast prawidłowej nazwy wyjściowej selectionChange. Angular 9 z strictTemplateswłączoną flagą wcale mi nie pomógł. Po cichu zawiodło. Interesujące jest to, że jeśli zrobię to samo @Input, aplikacja złapie błąd (błędy) i się nie skompiluje.

Czy istnieje jakiś sposób, aby zgłosić błąd, jeśli próbuję „wysłuchać” nieistniejącego @Output?

dev_054
źródło
1
czy były jakieś błędy w poprzednich wersjach Angulara? Myślę, że nigdy nie rzuciło to w żaden błąd
Aravind
@Aravind nie, nigdy nie rzucał błędów. Pytam, czy to możliwe. Z góry dziękuję.
dev_054
dlaczego chcesz rzucić błąd? czy jest jakaś konkretna potrzeba? Próbuję zrozumieć twoje pytanie
Aravind
@ Dobrze, pracuję nad aplikacją dla przedsiębiorstw z wieloma programistami, dlatego ważne jest, aby mieć jakieś informacje / ostrzeżenia / błędy. Czasami ktoś zmienia / usuwa @Output()bibliotekę współdzieloną lub nawet w aplikacji i zapomina usunąć połączenia ... a ponieważ nie mamy błędów kompilacji, tak jak my @Input(), nie możemy znaleźć dokładnie tego, co powoduje pewne problemy (lub nawet za brak przechowywania śmieci w kodzie). Testy jednostkowe mogą być pomocne? Może, ale w tej chwili nie jest to jeszcze możliwe ze względu na czas.
dev_054

Odpowiedzi:

3

Nie ma błędu rzucony ponieważ wiązanie wydarzenie w kątowej służy nie tylko z @OutputS i EventEmitterS, ale również słuchać zdarzeń DOM , takich jak click, keyupitd To może być nawet używany do słuchania niestandardowych zdarzeń . Na przykład, jeśli utworzysz i wyślesz niestandardowe zdarzenie w komponencie potomnym:

constructor (private el: ElementRef) {}
ngOnInit(): void {
    const domEvent = new CustomEvent('selectedChange', { custom: true });
    this.el.nativeElement.dispatchEvent(domEvent);
}

Następnie w komponencie nadrzędnym możesz złapać go po nazwie:

<app-test (selectedChange)="selectedChangeHandler($event)"></app-test>

Angular używa target.addEventListener (typ, detektor [, opcje]); wewnętrznie (możesz się upewnić, patrząc na poniższe linki), gdzie typemoże być dowolny ciąg.

Dlatego nie zgłasza żadnego wyjątku, jeśli nie znajdzie pasujących @Outputs.

listenToElementOutputs

DefaultDomRenderer2.listen

EventManager.addEventListener

DomEventsPlugin.addEventListener

Kirill Simonov
źródło
Cześć @Kirill Simonov dzięki za odpowiedź! Cóż, biorąc pod uwagę stwierdzenie: „Nie jest zgłaszany błąd, ponieważ wiązanie zdarzeń w Angular jest używane nie tylko z @Outputs i EventEmitters, ale także do nasłuchiwania zdarzeń DOM, takich jak kliknięcie, keyup itp.”, Dlaczego więc, jeśli zdasz nieistniejące @Input()(należy pamiętać, że Wejścia mają takie same właściwości: może być coś jak globalne disabled, iditd) kątowe rzucił błędy? Dlaczego to działa @Input, ale nie działa @Output? Próbuję również znaleźć sposób, aby ostrzec / wyrzucić błąd, jeśli nieistniejący przejdzie @Output.
dev_054
@ dev_054 dzieje się tak, ponieważ zestaw właściwości jest ograniczony przez istniejące właściwości elementu DOM, dyrektywy lub komponentu, więc Angular może łatwo sprawdzić, czy ta właściwość istnieje, czy nie. Z drugiej strony zdarzenia są powiązane addEventListener(dodam kilka linków do mojej odpowiedzi, aby ją pokazać). Myślę, że zostało to zrobione celowo, aby programiści mogli użyć powiązania zdarzeń z własnymi niestandardowymi zdarzeniami. Uważam, że nie ma sposobu, aby wyłączyć to zachowanie w czasie kompilacji. Chociaż niektóre IDE (jak Idea IntelliJ) mogą wyróżniać takie miejsca i wyświetlać ostrzeżenia.
Kirill Simonov
@ dev_054 pamiętać, że można również użyć do wiązania w jedną stronę HTML atrybuty używając [attr.any-attribute]w tym przypadku błąd nie zostanie wyrzucony albo.
Kirill Simonov
0

Nie ma bezpośredniego rozwiązania Twojego problemu, jednak niektóre przypadki mogą zostać objęte.

  1. Jeśli masz jakieś wyjście, które jest używane w 100% miejsc, takich jak clickzdarzenie przycisku , możesz uczynić go częścią selektora, tj selector: 'app-test[selectionChange]'. Możesz to również zrobić na przykład: selector: 'app-test[selectionChange]', app-test[click]'znaczy clicklub selectionChangejest wymagane.
  2. Jeśli refaktoryzacji kodu i wyjście rename IE selectionChange, aby selectedChangenastępnie można użyć tego selektor: selector: 'app-test:not([selectionChange])'dla użytkowników sił, aby zaktualizować.
kemsky
źródło
-4

Jeśli używasz VS Code, możesz zainstalować to rozszerzenie: Angular Language Service wyśle ​​ostrzeżenie, gdy metoda lub właściwość nie zostaną zdefiniowane. To rozszerzenie działa zarówno z wyjściami, jak i wejściami (i atrybutami itp.).

Identyfikator „XXXvalidateProvider” nie jest zdefiniowany.

srgrcp
źródło
Twoja próbka pokazuje @Input. W @OutputAngular Language Service nic nie pomaga. Daj mi znać, jeśli potrzebujesz wyjaśnienia pytania.
dev_054
Dla @Outputtego zobaczysz ten sam komunikat o błędzie.
srgrcp