Compruebe si la salida está presente en el componente

14

Considere el siguiente componente:

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

Con la llamada:

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

Tenga en cuenta que he escrito en selectedChangelugar del nombre de salida correcto selectionChange. Angular 9 con la bandera strictTemplateshabilitada no me ayudó en absoluto. Falló en silencio. La parte interesante es que si hago lo mismo @Input, la aplicación detecta los errores y no se compila.

¿Hay alguna forma de arrojar un error si trato de "escuchar" un inexistente @Output?

dev_054
fuente
1
¿Hubo algún error con las versiones anteriores de Angular? Creo que nunca arrojó ningún error en esto
Aravind
@Aravind no, nunca arrojó errores. Estoy preguntando si es posible. Gracias por adelantado.
dev_054
¿Por qué quieres tirar error? ¿hay una necesidad específica? Estoy tratando de entender tu pregunta
Aravind
@Aravind, estoy trabajando en una aplicación empresarial con muchos desarrolladores, por lo que es importante tener algún tipo de información / advertencia / error. A veces, alguien cambia / elimina una @Output()en una biblioteca compartida, o incluso en la aplicación, y se olvida de eliminar las llamadas ... y como no tenemos errores de compilación, como lo hemos hecho @Input(), no podemos encontrar exactamente qué causa ciertos problemas (o incluso por no guardar basura en el código). ¿Las pruebas unitarias pueden ser útiles? Tal vez, pero en ese momento aún no es posible debido al tiempo.
dev_054

Respuestas:

3

No hay error tirado porque el suceso de unión en angular se utiliza no sólo con @Outputs y EventEmitters, sino también para escuchar a los eventos DOM tales como click, keyup, etc. Incluso se podría utilizar para escuchar eventos personalizados . Por ejemplo, si crea y emite un evento personalizado en el componente secundario:

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

Luego, en el componente principal, puede atraparlo por su nombre:

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

Angular usa target.addEventListener (type, listener [, options]); internamente (puede asegurarse de que typevea los enlaces a continuación), donde podría haber cualquier cadena.

Es por eso que no arroja ninguna excepción si no encuentra @Outputs coincidentes .

listenToElementOutputs

DefaultDomRenderer2.listen

EventManager.addEventListener

DomEventsPlugin.addEventListener

Kirill Simonov
fuente
Hola @Kirill Simonov gracias por tu respuesta! Bueno, tomando su declaración: "No se produce ningún error porque el enlace de evento en Angular se usa no solo con @Outputs y EventEmitters, sino también para escuchar los eventos DOM como clic, keyup, etc.", ¿por qué entonces si pasa? una inexistente @Input()(recordar que las entradas tienen las mismas características: puede ser algo global como disabled, id, etc.) angular arrojó errores? ¿Por qué funciona @Input, pero no para @Output? Además, estoy tratando de encontrar una manera de advertir / lanzar un error si @Outputse pasa un inexistente .
dev_054
@ dev_054 esto se debe a que el conjunto de propiedades está limitado por las propiedades existentes de un elemento DOM, directiva o componente, por lo que Angular puede verificar fácilmente si esta propiedad existe o no. Los eventos, por otro lado, están vinculados usando addEventListener(agregaré algunos enlaces a mi respuesta para mostrarlo). Creo que se hizo intencionalmente, por lo que los desarrolladores podrían usar el enlace de eventos con sus propios eventos personalizados. Creo que no hay forma de deshabilitar este comportamiento en tiempo de compilación. Aunque algunos IDE (como IntelliJ Idea) pueden resaltar dichos lugares y mostrar advertencias.
Kirill Simonov
@ dev_054 recuerde que también puede usar el enlace unidireccional para atributos HTML usando [attr.any-attribute], en este caso tampoco se generará ningún error.
Kirill Simonov
0

No hay una solución directa a su problema, sin embargo, algunos casos pueden estar cubiertos.

  1. Si tiene alguna salida que se utiliza en el 100% de los lugares, como el clickevento de botón , puede hacerla parte del selector, es decir selector: 'app-test[selectionChange]'. También puede hacer esto, por ejemplo: selector: 'app-test[selectionChange]', app-test[click]'significado clicko selectionChangees obligatorio.
  2. Si se reestructuran código y la salida es decir, cambio de nombre selectionChangea selectedChangecontinuación, puede utilizar este selector: selector: 'app-test:not([selectionChange])'para los usuarios de la fuerza para la actualización.
kemsky
fuente
-4

Si está utilizando VS Code, puede instalar esta extensión: Angular Language Service lanzará una advertencia cuando no se defina un método o propiedad. Esta extensión funciona tanto con salidas como con entradas (y atributos, etc.).

El identificador 'XXXvalidateProvider' no está definido.

srgrcp
fuente
Su muestra muestra una @Input. Para @Output, Angular Language Service no ayuda en nada. Avíseme si necesita que aclare la pregunta.
dev_054
Para un @Outputverás el mismo mensaje de error.
srgrcp