Verifique se a saída está presente no componente

14

Considere o seguinte componente:

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

Com a ligação:

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

Observe que eu escrevi em selectedChangevez do nome de saída correto selectionChange. O Angular 9 com a bandeira strictTemplatesativada não me ajudou em nada. Falha silenciosamente. A parte interessante é que, se eu fizer o mesmo @Input, o aplicativo detectará o (s) erro (s) e não será compilado.

Existe alguma maneira de gerar um erro se eu tentar "ouvir" um inexistente @Output?

dev_054
fonte
11
houve algum erro nas versões anteriores do Angular? Eu acho que nunca lançou nenhum erro sobre isso
Aravind
@ Aravind não, nunca gerou erros. Estou perguntando se é possível. Desde já, obrigado.
dev_054 27/02
por que você quer lançar erro? existe uma necessidade específica? Estou tentando entender sua pergunta.
Aravind
@ Bem, estou trabalhando em um aplicativo corporativo com muitos desenvolvedores, por isso é importante ter algum tipo de informação / aviso / erro. Às vezes, alguém altera / remove uma @Output()lib compartilhada ou até mesmo no aplicativo e esquece de remover as chamadas ... e como não temos erros de compilação, como temos @Input(), não conseguimos encontrar exatamente o que causa certos problemas (ou mesmo por não guardar lixo no código). Testes de unidade podem ser úteis? Talvez, mas no momento ainda não é possível devido ao tempo.
dev_054 28/02

Respostas:

3

Não há erro lançado porque a ligação de evento em angular é usado não só com @Outputs e EventEmitters, mas também para ouvir os eventos DOM , como click, keyup, etc. Pode até ser usado para ouvir eventos personalizados . Por exemplo, se você criar e emitir um evento personalizado no componente filho:

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

Em seguida, no componente pai, você pode identificá-lo pelo nome:

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

Angular usa target.addEventListener (tipo, ouvinte [, opções]); internamente (você pode verificar isso nos links abaixo), onde typepode haver qualquer string.

É por isso que não lança nenhuma exceção se não encontrar @Outputs correspondentes .

listenToElementOutputs

DefaultDomRenderer2.listen

EventManager.addEventListener

DomEventsPlugin.addEventListener

Kirill Simonov
fonte
Hey @Kirill Simonov, obrigado pela sua resposta! Bem, considerando sua afirmação: "Não há erro lançado porque a ligação de evento no Angular é usada não apenas com @Outputs e EventEmitters, mas também para ouvir eventos do DOM, como clique, keyup, etc.", por que então se você passar um inexistente @Input()(lembre-se que as entradas têm as mesmas características: pode ser algo global como disabled, id, etc.) angular jogou erros? Por que funciona para @Input, mas não para @Output? Além disso, estou tentando encontrar uma maneira de avisar / lançar erro se um inexistente @Outputfor passado.
dev_054 27/02
@ dev_054 isso ocorre porque o conjunto de propriedades é limitado pelas propriedades existentes de um elemento, diretiva ou componente DOM, portanto o Angular pode verificar facilmente se essa propriedade existe ou não. Os eventos, por outro lado, são vinculados ao uso addEventListener(adicionarei alguns links à minha resposta para mostrá-la). Eu acho que foi feito intencionalmente, para que os desenvolvedores pudessem usar a associação de eventos com seus próprios eventos personalizados. Acredito que não há como desativar esse comportamento no momento da compilação. Embora alguns IDEs (como o IntelliJ Idea) possam destacar esses locais e exibir avisos.
Kirill Simonov
@ dev_054 lembre-se de que você também pode usar uma ligação unidirecional para atributos HTML usando [attr.any-attribute], neste caso, nenhum erro será gerado.
Kirill Simonov 27/02
0

Não há solução direta para o seu problema, no entanto, alguns casos podem ser abordados.

  1. Se você tiver alguma saída usada em 100% dos locais, como clickevento de botão , poderá fazer parte do seletor, por exemplo selector: 'app-test[selectionChange]'. Além disso, você pode fazer isso por exemplo: selector: 'app-test[selectionChange]', app-test[click]'significado clickou selectionChangeé necessário.
  2. Se você estiver refatorando o código e renomeando a saída, ou seja, selectionChangepara selectedChangeisso, poderá usar este seletor: selector: 'app-test:not([selectionChange])'para forçar os usuários a atualizar.
kemsky
fonte
-4

Se você estiver usando o Código VS, poderá instalar esta extensão: O Angular Language Service emitirá um aviso quando um método ou propriedade não estiver definido. Esta extensão funciona com saídas e entradas (e attrs, etc ...).

O identificador 'XXXvalidateProvider' não está definido.

srgrcp
fonte
Sua amostra mostra um @Input. Pois @Output, o Angular Language Service não ajuda em nada. Deixe-me saber se você precisa que eu esclareça a pergunta.
dev_054 27/02
Para um, @Outputvocê verá a mesma mensagem de erro.
srgrcp 27/02