Verificare se sul componente è presente l'output


14

Considera il seguente componente:

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

Con la chiamata:

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

Si noti che ho scritto selectedChangeinvece del nome di output corretto selectionChange. Angular 9 con la bandiera strictTemplatesabilitata non mi ha aiutato affatto. È fallito silenziosamente. La parte interessante è che se faccio la stessa cosa per @Input, l'app cattura gli errori e non si compila.

C'è un modo per lanciare un errore se provo ad "ascoltare" un inesistente @Output?


1
ci sono stati errori con le versioni precedenti di Angular? Penso che non abbia mai gettato alcun errore su questo
Aravind il

@Aravind no, non ha mai gettato errori. Sto chiedendo se è possibile. Grazie in anticipo.
dev_054,

perché vuoi lanciare un errore? c'è un bisogno specifico? Sto cercando di capire la tua domanda
Aravind,

@Aravind bene, sto lavorando su un'app aziendale con molti sviluppatori, quindi è importante avere qualche tipo di informazione / avviso / errore. A volte qualcuno cambia / rimuove un @Output()in una lib condivisa, o persino sull'app e dimentica di rimuovere le chiamate ... e poiché non abbiamo errori di compilazione, come abbiamo fatto per @Input(), non riusciamo a trovare esattamente ciò che causa determinati problemi (o anche per non tenere la spazzatura nel codice). I test unitari potrebbero essere utili? Forse, ma al momento non è ancora possibile a causa del tempo.
dev_054,

Risposte:


3

Non v'è alcun errore gettato perché l' evento di legame in angolare viene utilizzato non solo con @Outputs e EventEmitters, ma anche per ascoltare gli eventi DOM , come click, keyupecc Potrebbe anche essere usato per ascoltare gli eventi personalizzati . Ad esempio, se si crea ed emette un evento personalizzato nel componente figlio:

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

Quindi nel componente padre puoi prenderlo con il suo nome:

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

Angular utilizza target.addEventListener (tipo, listener [, opzioni]); internamente (puoi assicurarti di guardare i link qui sotto), dove typepotrebbe esserci qualsiasi stringa.

Ecco perché non genera alcuna eccezione se non trova messaggi corrispondenti @Output.

listenToElementOutputs

DefaultDomRenderer2.listen

EventManager.addEventListener

DomEventsPlugin.addEventListener


Ciao @Kirill Simonov, grazie per la tua risposta! Bene, prendendo la tua affermazione: "Non viene generato alcun errore perché il binding di eventi in Angular viene utilizzato non solo con @Outputs ed EventEmitters, ma anche per ascoltare gli eventi DOM come clic, keyup, ecc", perché allora se si passa un inesistente @Input()(ricordiamo che gli ingressi hanno le stesse caratteristiche: può essere qualcosa di globale come disabled, ide così via) angolare gettato errori? Perché funziona per @Input, ma non per @Output? Inoltre, sto cercando di trovare un modo per avvisare / lanciare un errore se @Outputviene superato un inesistente .
dev_054,

@ dev_054 questo perché l'insieme di proprietà è limitato dalle proprietà esistenti di un elemento DOM, direttiva o componente, in modo che Angular possa facilmente verificare se questa proprietà esiste o no. Gli eventi, d'altra parte, vengono associati utilizzando addEventListener(aggiungerò alcuni collegamenti alla mia risposta per mostrarlo). Penso che sia stato fatto intenzionalmente, in modo che gli sviluppatori possano utilizzare il binding di eventi con i propri eventi personalizzati. Credo che non ci sia modo di disabilitare questo comportamento al momento della compilazione. Sebbene alcuni IDE (come IntelliJ Idea) possano evidenziare tali luoghi e visualizzare avvisi.
Kirill Simonov,

@ dev_054 ricordare che si potrebbe anche usare vincolante per sola andata attributi HTML usando [attr.any-attribute], in questo caso, nessun errore sarà gettato neanche.
Kirill Simonov,

0

Non esiste una soluzione diretta al tuo problema, tuttavia alcuni casi possono essere coperti.

  1. Se si dispone di qualsiasi output utilizzato nel 100% di luoghi come l' clickevento pulsante , è possibile renderlo parte del selettore, ad es selector: 'app-test[selectionChange]'. Inoltre puoi farlo per esempio: selector: 'app-test[selectionChange]', app-test[click]'significato clicko selectionChangeè richiesto.
  2. Se si refactoring del codice e cioè l'uscita rinomina selectionChangea selectedChangequindi è possibile utilizzare questo selettore: selector: 'app-test:not([selectionChange])'per gli utenti di forza di aggiornamento.

-4

Se si utilizza VS Code è possibile installare questa estensione: Angular Language Service genererà un avviso quando un metodo o una proprietà non sono definiti. Questa estensione funziona con entrambi, output e input (e attrs, ecc ...).

L'identificatore 'XXXvalidateProvider' non è definito.


Il tuo esempio mostra un @Input. Perché @Output, Angular Language Service non aiuta a nulla. Fammi sapere se hai bisogno di me per chiarire la domanda.
dev_054,

Per un @Outputcerto vedrai lo stesso messaggio di errore.
srgrcp,
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.