Angular: EXCEÇÃO: a expressão mudou depois de ser verificada.

Criado em 18 dez. 2015  ·  147Comentários  ·  Fonte: angular/angular

Comentários muito úteis

Isso não é um bug, é um recurso do modo dev funcionando conforme o esperado. Chamando enableProdMode( ) - veja o plunk atualizado ao inicializar o aplicativo evita que a exceção seja lançada.

Dito isso, está sendo lançado por um bom motivo: em suma, após cada rodada de detecção de alteração, o modo dev executa imediatamente uma segunda rodada para verificar se nenhuma ligação foi alterada desde o final da primeira, pois isso indicaria que as alterações estão sendo causadas pela própria detecção de alterações.

Em seu plunk, você tem a ligação [attr.spinner]=isLoading , e isLoading muda como resultado de sua chamada para this.load() , que ocorre quando ngAfterViewInit é disparado, que acontece como parte do turno de detecção de mudança inicial. Porém, isso em si não é problemático - o problema é que this.load() altera uma associação, mas não aciona uma nova rodada de detecção de alterações, o que significa que essa associação não será atualizada até alguma rodada futura de detecção de alterações.

Todos 147 comentários

Tenho enfrentado um problema semelhante e parece ser devido a como um filho é inicializado e como um pai pode atualizar o filho como parte de seu processo de inicialização. Eu tenho uma amostra semelhante com uma solução alternativa feia usando zona: http://plnkr.co/edit/GI45u805pnFUtFeORnxn?p=preview , com a solução alternativa parecida com a seguinte:

construtor (private _zone: NgZone) {}

ngAfterViewInit (): void {
this._zone.overrideOnTurnDone (() => {
this.child.title = 'título do pai';
});
}

Isso não é um bug, é um recurso do modo dev funcionando conforme o esperado. Chamando enableProdMode( ) - veja o plunk atualizado ao inicializar o aplicativo evita que a exceção seja lançada.

Dito isso, está sendo lançado por um bom motivo: em suma, após cada rodada de detecção de alteração, o modo dev executa imediatamente uma segunda rodada para verificar se nenhuma ligação foi alterada desde o final da primeira, pois isso indicaria que as alterações estão sendo causadas pela própria detecção de alterações.

Em seu plunk, você tem a ligação [attr.spinner]=isLoading , e isLoading muda como resultado de sua chamada para this.load() , que ocorre quando ngAfterViewInit é disparado, que acontece como parte do turno de detecção de mudança inicial. Porém, isso em si não é problemático - o problema é que this.load() altera uma associação, mas não aciona uma nova rodada de detecção de alterações, o que significa que essa associação não será atualizada até alguma rodada futura de detecção de alterações.

Eu preciso configurar meu componente em afterViewInit porque tenho ChildView inicializado aqui. Qual é a maneira correta de fazer essa alteração em isLoading ? Encerrar a chamada para this.load por setTimeout ?

Você só precisa fazer algo, qualquer coisa, que acione outra rodada de detecção de alterações durante esse método - emitir um evento, seja o que for. Envolvê-lo em um tempo limite (flashback da fila para ng1 :-P) é uma maneira que funcionaria, mas parece muito confuso para mim no ng2.

Não parece amigável. Penso nesse método como o lugar onde posso concluir a inicialização do meu componente quando seus filhos são definidos e agora descobri que ele tem algumas regras personalizadas. Acho que você deve forçar internamente uma nova rodada de detecção de alterações para que ela fique oculta dentro do ng2 do usuário.

você poderia postar uma amostra mais representativa do que você está tentando alcançar aqui? se for o seu spinner de imagem, seria melhor usar uma encadernação padrão.

@ AerisG222 idem para você. há alguma razão pela qual você não pode usar uma ligação simples para fazer isso? substituir o comportamento da zona normalmente não é recomendado.

@robwormald Sim, nesse caso eu poderia fazer a vinculação de propriedade. O caso real que eu tenho também envolve outra propriedade que é um pouco mais complicada - uma matriz de objetos personalizados, mas que certamente poderia ser definida por meio de associação de propriedade.

Suponho que, se não existisse @ViewChild , eu não me importaria muito, pois essa seria a única maneira razoável de passar as informações adiante. No entanto, eu estava muito animado para ver @ViewChild para que eu pudesse trabalhar fora disso para referências de componentes no código. Isso simplifica a marcação e permite mais controle por meio do código, o que é adicionalmente valioso com o typescript, pois há mais suporte de ferramentas (como intellisense e verificação de tempo de compilação). Ele também simplifica o componente do contêiner, pois não precisa rastrear variáveis ​​de membro que devem ser usadas apenas como estado para o filho.

Outro ponto secundário é que, ao examinar um aplicativo usando a sintaxe de vinculação de propriedade, você deve inspecionar o modelo para ver quem está consumindo os dados. Isso seria mais óbvio quando conectado via código.

Limpei o código para mostrar apenas o que importa para o exemplo. A ideia é mostrar o spinner apenas enquanto a imagem está carregando e, em seguida, remover o spinner e mostrar a imagem. A imagem é carregada apenas quando o elemento está visível na tela.

inflate.ts

import {Component, Input, Renderer, ElementRef, AfterViewInit, ViewChild} from 'angular2/core';

@Component({
  selector: '[inflate]',
  templateUrl: './inflate.html',
  styleUrls: ['./inflate.css']
})
export class Inflate implements AfterViewInit {
  @Input('inflate') url: string;
  @ViewChild('holder') holder: ElementRef;
  isLoaded = false;
  isLoading = false;

  constructor(private renderer: Renderer) {}

  ngAfterViewInit() {
    setTimeout(_=> this.inflate()); // BUGFIX: https://github.com/angular/angular/issues/6005#issuecomment-165911194
  }

  inflate() {
    let bounds = <ClientRect>this.holder.nativeElement.getBoundingClientRect();
    if(bounds.bottom > 0 && bounds.top < window.innerHeight) {
      this.isLoading = true;
      let img = new Image();
      img.src = this.url;
      img.onload = _=> {
        this.isLoaded = true;
        this.isLoading = false;
        this.renderer.setElementStyle(this.holder,
          'background-image', 'url("' + this.url + '")');
      };
    }
  }
}

inflate.html

<image-holder #holder></image-holder>
<spinner *ngIf="isLoading"></spinner>

Preciso manter a imagem fora do host porque, embora ela apareça gradualmente com a animação no carregamento completo, não deve afetar a opacidade do plano de fundo do host.

Eu tenho um problema potencialmente relacionado com uma diretiva aninhada.
http://plnkr.co/edit/myX2Alx9jie2q0FDIME7?p=preview
Aqui, estou vinculando a ngStyle no progressBar.ts.
Estou registrando o objeto styles antes de retornar para provar que eles são iguais.
Eu também obtenho a ExpressionChangedAfterItHasBeenCheckedException.

@ svi3c você está realmente retornando um objeto _diferente_. Cada chamada de função retornará uma nova instância de objeto que é "igual" à anterior em termos de chaves / valores, mas não em termos de instâncias / referências.

Existem várias maneiras de lidar com esta situação:

  • atualizar valores em uma instância de objeto, em vez de retornar uma nova cópia
  • usando a estratégia ChangeDetectionStrategy.OnPush para que sua função seja invocada apenas quando uma das entradas mudar, ex: http://plnkr.co/edit/NWyVoTtkiAzqWJphLMbi?p=preview

Você pode querer verificar https://github.com/ng-bootstrap/core/blob/master/src/progressbar/progressbar.ts como outro exemplo de uma diretiva progressbar para ng2 (usando HTML / CSS do bootstrap)

@ pkozlowski-opensource Muito obrigado!
Eu só li https://angular.io/docs/ts/latest/guide/template-syntax.html#!#ngstyle e não tropecei nas estratégias de detecção de alterações ainda. Isso é ótimo! :)

@drew-moore:

Você só precisa fazer algo, qualquer coisa, que acione outra rodada de detecção de alterações durante esse método - emitir um evento, seja o que for.

Você pode aconselhar qual é a maneira _correta_ e _simplesta_ de disparar novamente a detecção de alterações em ngAfterViewInit - assumindo que tudo o que é necessário é uma propriedade a ser atualizada. ApplicationRef.tick() não funciona aqui, pois isso causa a exceção 'ApplicationRef.tick é chamado recursivamente'; emitir um evento apenas para acionar uma detecção de mudança parece errado (e não funcionou para mim), assim setTimeout .

Com base nos comentários aqui, parece ser um requisito bastante comum atualizar uma propriedade vinculada em ngAfterViewInit (devido a uma dependência de um componente filho), então Angular 2 parece não ter uma maneira simples de fazer isso.

Se atualizar uma propriedade vinculada em ngAfterViewInit for a coisa _ errada_ a fazer, qual é a alternativa?

Aqui está um rápido:

Desafio:
Defina a altura do elemento dom (por meio de uma certa fórmula) com base em sua largura renderizada.

Expectativa:
Quando o elemento é renderizado, obtenha a largura e, com base nela, calcule sua altura.

Realidade:
setTimeout ?!

  ngAfterViewInit() {
    window.setTimeout(() =>
      this.elementHeight = (this.nativeElement.offsetWidth * this.randomImage.dim.h) / this.randomImage.dim.w
    )
  }

@Birowsky Plunker?

@zoechi Aqui está um exemplo: http://plnkr.co/edit/MML5uHEFQdL0k0TA5HtY

Você pode alternar o setTimeout em app/app.component.ts#21 no gancho do ciclo de vida ngAfterViewInit .

Também encontrei algo semelhante ao tentar implementar o método writeValue( newValue ) de um ngModel valueAccessor . Quando tento aplicar o newValue ao componente, ele me diz que o valor mudou (de um jeito ruim). Como todos vocês descobriram, envolvê-lo em um setTimeout () "corrige"; Mas não de um jeito bom.

Eu tenho outro exemplo . É um pouco mais simples porque @HostBinding() é configurado e informado por QueryList .

Igual ao meu problema # 5950.

Algumas recomendações aqui sobre como fazer isso de forma limpa.
http://stackoverflow.com/questions/34827334/triggering-angular2-change-detection-manually

No entanto, ainda estou envolvendo setTimeout porque não consegui que nenhum deles fizesse o que eu preciso. Parece que eu poderia ChangeDetectorRef.detectChanges() no final de um retorno de chamada e acionar o CD .... Estou esquecendo de algo? Talvez ajude um de vocês.

Estou usando as extensões de fonte de mídia HTML5 para criar um contexto de áudio com base em um elemento de vídeo, portanto, o uso de @ViewChild é obrigatório. Com base no contexto de áudio, estou tentando exibir algumas informações, como número de canais. No entanto, também encontrei esse problema. Qual é a maneira certa de contornar isso?

@ElsewhereGames Difícil dizer sem ver algum código real. Você pode criar um Plunker

@zoechi Não tenho um bug real para relatar, apenas afirmando que não acessar o DOM diretamente, embora desejável, nem sempre é algo que pode ser evitado (em resposta ao comentário @robwormald ). Para a API atual , consulte os documentos em

Postei em janeiro com um problema _ngModel_. Agora, estou de volta com o problema _ViewChildren_. No entanto, ao contrário de alguns desses outros exemplos, não estou realmente tentando fazer nada na minha demonstração. Ou seja, meus controladores têm lógica zero - são todos metadados e associações de visualização. Como tal, não tenho certeza de onde tenho espaço de manobra para _mensar as coisas_:

http://www.bennadel.com/blog/3040-i-have-a-fundamental-misunderstanding-of-change-detection-in-angular-2-beta-8.htm

Encontrando um problema semelhante, mas poderia reescrever o código para contorná-lo. Eu dei uma boa risada com o post @bennadel, então obrigado. Compartilhe alguns dos sentimentos que tive com problemas anteriores, nos quais a detecção inteligente de alterações não era inteligente o suficiente, muito inteligente ou muito inteligente para mim :-)

https://github.com/angular/angular/issues/6618

Até agora, sempre houve uma maneira de contornar isso, mas vou sugerir aqui novamente, pelo menos o mecanismo de detecção de alterações poderia usar mais documentação. @bennadel Seu problema me lembra de outro problema,

https://github.com/angular/angular/issues/5177

onde resolver isso, foi sugerido que o gancho de ciclo de vida extra fosse adicionado OnBeforeBinding / OnBeforeRendering. Parece que essa solução também resolveria seu problema.

@tandu apenas substitua ngAfterViewInit por ngOnInit

@tandu realmente não importa quando seu spinner iniciará (carregando filho, carregando imagem em criança - para o usuário tudo está carregando), só importa quando você precisa desligá-lo. Você pode desligá-lo em "ngAfterViewInit", usando setTimeout (concordo que é feio), mas estará errado - o componente filho deve disparar um evento quando o carregamento da imagem for concluído, para o componente pai. Carregar componente filho e carregar imagem são 2 eventos diferentes.

@ e-oz https://github.com/angular/angular/issues/6005#issuecomment -165951692 Acesso aos limites do filho para detectar se devo iniciar o carregamento da imagem.

@tandu e você poderia mover toda essa verificação para o código do componente filho (seria legítimo em ngAfterViewInit do componente filho) e enviar o evento para o pai, quando alterar isLoading.

@ e-oz eu defino o componente como #holder em html: <image-holder #holder></image-holder> . Portanto, não há nenhum arquivo js para isso.

então crie-o, caso contrário, não há necessidade de usar ngAfterViewInit, se View
não tem componentes reais como filhos - nada será renderizado.

No domingo, 13 de março de 2016 às 15:18 tandu [email protected] escreveu:

@ e-oz https://github.com/e-oz Eu defino o componente como #holder em html:

titular>

. Portanto, não há nenhum arquivo js para isso.

-
Responda a este e-mail diretamente ou visualize-o no GitHub
https://github.com/angular/angular/issues/6005#issuecomment -195963389.

Também posso usar element.getElementsByTagsName ou métodos semelhantes e não usar ChildComponent. Definitivamente existem soluções alternativas. Estou bem com a correção de setTimeout . O problema é que o nome do método sugere que ele pode ser usado para definir alguma lógica que deseja que os componentes filhos sejam inicializados e vinculados ao componente, mas o método não diz que ele é executado no meio do ciclo de detecção de mudança e, portanto, temos um longo fio de reclamações de pessoas diferentes.

@tandu Eu concordo

Pelo que vale a pena, mudei minha solução original para o seguinte, que está começando a parecer uma abordagem razoável. Talvez valha a pena tentar para a sua situação:

    constructor(private _changeDetectionRef : ChangeDetectorRef) { }

    ngAfterViewInit() : void {
        // your code

        this._changeDetectionRef.detectChanges();
    }

Estou recebendo a mesma exceção ao usar a validação de formulário (entrada necessária). Relacionado a este problema?

Plunker: http://plnkr.co/edit/Fp6XT5mC6ZCB14Z1gvTi?p=preview

@eivindr deu uma olhada rápida e eu não tinha visto ngFormControl em uma entrada antes, não consigo ver por que ou o que significaria, pois deveria ir no elemento do formulário para vinculá-lo a um grupo de controle e a entrada individual teria um correspondente ngControl. Em qualquer caso, remova o êmbolo

 [ngFormControl]="formModel.find('title')" 

e corrige o seu erro.

Recuso-me a abandonar este problema :) Ontem, consegui demonstrar que meu problema estava especificamente relacionado a ligações de host que dependem de propriedades de entrada :

http://www.bennadel.com/blog/3056-host-bindings-are-breaking-the-ngmodel-bridge-in-angular-2-beta-11.htm

Eu tenho que acreditar que este é um bug neste ponto porque o componente tem duas coisas que dependem da entrada - o modelo de exibição e as ligações de host - e _apenas um deles_ está causando a exceção de alteração. Se ambos causassem o problema, eu pensaria em outra coisa; mas, como apenas um deles está causando o problema, deve ser um bug, certo?

@eivindr Também tenho o mesmo problema ao começar com um formulário em branco e, em seguida, definir o valor dos controles do formulário de forma programática. Você encontrou uma solução?

@MarkPerryBV Não, ainda recebo "mudou após ter sido verificado" ao usar obrigatório. Mesmo ao usar o validador de padrão. Mas minLength etc funciona.

@ user414 Se eu remover [ngFormControl] ... não há validação "necessária" na entrada.

@MarkPerryBV Eu encontrei uma solução alternativa que funciona para mim (por enquanto). Tive que ativarProdMode (). Estou usando ngIf nas entradas, então também tive que fazer um ChangeDetectorRef.detectChanges () depois que a entrada foi renderizada (se não, a entrada era inválida apesar de ter conteúdo).

Usar enableProdMode() realmente não corrige nada - apenas mascara o sintoma, impedindo-o de fazer a verificação dupla e informando que algo provavelmente está errado.

A correção do AerisG222 parece melhor do que usar um setTimeout . É realmente o caso em que o comportamento pretendido é ter que acionar manualmente a detecção de alterações após chamar addControl() com um validador?

O mesmo problema aqui após chamar addControl (). Acho que addControl () deve chamar ChangeDetectionRef.detectChanges ().

@CaptainCodeman eu sei - era uma solução temporária.

Isso não falhará mais no modo dev quando estou usando ng2 @ beta17 , [email protected] , zone. [email protected]. Ainda tenho que chamar ChangeDetectionRef.detectChanges ()

@eivindr você pode atualizar seu plnkr para a correção beta17?
Estou perdendo a cabeça por causa disso, recuso-me a me submeter a enableProdMode() .

@ AerisG222 Sua abordagem funciona para mim!

Usar a abordagem que @ AerisG222 postou uma boa abordagem para usar? Sim, funciona, mas há alguma consciência de acionar manualmente changeDetectionRef.detectChanges() ?

Estou tendo o mesmo problema ao tentar fazer a validação dinâmica do formulário e, em seguida, redefinir o formulário. aqui está meu plunk

Passos para reproduzir. Envie o formulário com Is Employee Checked. Após a atualização do formulário, marque Is Employee novamente.

Estou usando o changeDetectionRef.detectChanges () na função de envio.

obrigado por isso @ AerisG222 :)

Não gosto de toda aquela solução alternativa setTimeout. Eu proponho o seguinte:

http://plnkr.co/edit/9umnTGsdFWhbaOBeftuZ?p=preview

Usar ChangeDetectorRef.detectChanges nem sempre é uma boa abordagem. Exemplo por que:

O componente pai chama os componentes do filho API pública durante seu ngAfterViewInit . Esta chamada altera o vínculo da criança. Chamar detectChanges do pai resolveria o problema também, mas isso significa que o pai deve saber quando chamar detectChanges após a chamada de API do filho. Você notará que chamar detectChanges no método childs que altera a ligação neste caso não funciona quando você deseja usar ChangeDetectionStrategy.OnPush .

Encontrei este erro ao adicionar dinamicamente os filhos por meio de ViewContainerRef.createComponent() e, em seguida, atualizar a instância do filho. Estou usando RC2 (e tentando não usar coisas depreciadas).

Inicialmente, a coisa funcionou bem (primeira renderização), mas depois adicionei um componente que emitiria novos dados. Este evento foi ouvido pelo componente pai, que atualizou seu array de dados, acionando a detecção de mudanças e o preenchimento de novos componentes filhos dinâmicos. O evento foi acionado por um envio de formulário. Se eu pressionasse o botão enviar, tudo correria bem. Se eu pressionar Enter para gerar o envio, ocorrerá o erro.

Acabei adicionando ChangeDetectorRef.detectChanges() imediatamente após a criação e atualização do componente dinâmico. Não é um grande problema, mas parece estranho que, embora eu tenha acabado de adicionar um novo componente à visualização, o sistema não aciona automaticamente a detecção de alterações para a criança.

@ aerisg222 Preciso chamar this._changeDetectionRef.detectChanges () Depois que cada propriedade dos filhos muda do pai?

Bem, acabei de encontrar esse problema. Tenho dois componentes irmãos usando o mesmo objeto de dados. Ambos os objetos devem ser capazes de atualizar a fonte de dados. A outra origem realmente vê a mudança no objeto, mas aciona a alteração da Expressão após ser verificada. Valor anterior: 'true'. Valor atual: 'false'

Isso aconteceu comigo depois de atualizar de RC1 para RC4

Mesmo aqui. Comecei a receber isso novamente após a atualização de RC1 para RC4.

Talvez a mudança que causou isso devesse ter sido comunicada como uma alteração interrompida no log de alterações ... kuz meu material está quebrado agora.

Precisamos esperar pelo final.
Parei de usar componentes filhos porque atualizar propriedades externas é uma droga.
Achei que as zonas estavam aqui para isso ...

Mesmo aqui. O carregamento do componente dinâmico via ViewComponentRef parece se comportar de maneira diferente no RC2 e RC4, assim como no RC1

Aqui estão minhas dependências de trabalho:
"dependências": {
"@ angular / comum": "2.0.0-rc.1",
"@ angular / compilador": "2.0.0-rc.1",
"@ angular / core": "2.0.0-rc.1",
"@ angular / http": "2.0.0-rc.1",
"@ angular / platform-browser": "2.0.0-rc.1",
"@ angular / platform-browser-dynamic": "2.0.0-rc.1",
"systemjs": "0.19.31",
"core-js": "^ 2.4.0",
"refletir-metadados": "^ 0.1.3",
"rxjs": "5.0.0-beta.6",
"zone.js": "^ 0,6.12"
},
"devDependencies": {
"texto datilografado": "^ 1.8.10",
"digitações": "^ 1.0.4",
"simultaneamente": "^ 2.2.0",
"servidor lite": "^ 2.2.2"
}

E aqui estão as dependências que estão produzindo o erro mencionado:
"dependências": {
"@ angular / comum": "2.0.0-rc.4",
"@ angular / compilador": "2.0.0-rc.4",
"@ angular / core": "2.0.0-rc.4",
"@ angular / http": "2.0.0-rc.4",
"@ angular / platform-browser": "2.0.0-rc.4",
"@ angular / platform-browser-dynamic": "2.0.0-rc.4",
"systemjs": "0.19.31",
"core-js": "^ 2.4.0",
"refletir-metadados": "^ 0.1.3",
"rxjs": "5.0.0-beta.6",
"zone.js": "^ 0,6.12"
},
"devDependencies": {
"texto datilografado": "^ 1.8.10",
"digitações": "^ 1.0.4",
"simultaneamente": "^ 2.2.0",
"lite-server": "^ 2.2.2"
}

RC2 também não está funcionando!

Só uma pergunta, mas há alguma maneira de obter mais informações sobre o erro? Por exemplo, seria bom saber o que é a "expressão" quando o erro diz "a expressão muda de 'verdadeiro' para 'falso' !.

Também estou tendo exatamente o mesmo problema depois de atualizar de RC1 para RC4. E o que descobri é devido à função ngOnInit em meu componente. Se eu comentar esta função, a mensagem de erro desaparece e tudo funciona bem. Alguma ideia?

Fechando este problema porque é antigo e as ações foram tomadas. Se você ainda tiver problemas, certifique-se de criar um novo problema e preencher o modelo de problema com todos os detalhes necessários . Obrigado

mas as pessoas diziam que ainda estão enfrentando esse problema no novo rc ...

Na quarta-feira, 13 de julho de 2016 às 00h52, Victor Berchet [email protected]
escreveu:

Fechado # 6005 https://github.com/angular/angular/issues/6005.

-
Você está recebendo isso porque foi mencionado.
Responda a este e-mail diretamente, visualize-o no GitHub
https://github.com/angular/angular/issues/6005#event -720794445 ou mudo
o segmento
https://github.com/notifications/unsubscribe/AAgIEFEVZmE0M53XxNpzAYg9hJT_E_viks5qVAyGgaJpZM4G4J_s
.

Sim, acabei de atualizar para RC4 e não fiz nenhuma alteração em nenhum dos meus componentes além de configurar um novo roteador e tive esse problema. Estava tudo bem no RC1, parece que ainda está por aí.

Mais informações:

Acontece que devido a async chamada dentro de ngOnInit , este erro ocorre. Se eu comentar o código de chamada assíncrona ou mover esse trecho de código para o construtor, tudo funcionará bem.

@ ammar91
Chame isso após as mudanças:
changeDetectionRef.detectChanges ()

@ zigzag95 Sim, esta é uma solução alternativa, mas parece super hacky fazer isso. Eu esperaria que uma estrutura como o angular lidasse com isso com mais elegância, em vez de nos obrigar a acionar manualmente seu próprio mecanismo de detecção de alterações.

No meu caso, está acontecendo quando estou assinando o emissor de evento angular em app.component.ts para mostrar e ocultar a barra de progresso. Estava tudo bem com o RC1, mas quebrou no RC4.

Aqui está a reprodução, http://plnkr.co/edit/jEtfUrQdc4sJBySj5kWN?p=preview
Clique no link Heroes e selecione um dos heróis para editar e você verá o erro.
Por favor, veja as mudanças em app.component.ts e hero.service.ts

Olá @vicb , obrigado pela atualização. Você pode nos dizer quais ações foram tomadas? Quer dizer que isso será consertado na próxima versão?

Outra solução alternativa simples que funcionou para mim é retornar o valor como observável e atrasar a emissão dos valores em 10 ms. No meu caso, a exceção estava ocorrendo com o valor giratório
<app-spinner *ngIf="spinner"></app-spinner>

  this.eventService.toggleSpinnerAnnounced$.subscribe(
      (show: boolean) => this.spinner = show
    );

isso funcionou para mim:

private spinner = new Subject<boolean>();
toggleSpinnerAnnounced$ = this.spinner.asObservable().delay(10); // This  delay() is important

announceSpinnerToggle(show: boolean) {
        this.spinner.next(show);
    }

Isso funcionou para você porque você está usando o atraso e não está relacionado ao observável.
Você terá o mesmo comportamento ao usar stettimeout.

@Jarvens, por favor, pare de postar este comentário em lugares impróprios.

Os problemas do GitHub são para relatórios de bugs e solicitações de recursos.
Para perguntas de suporte, use outros canais como os listados em CONTRIBUINDO - Tem uma pergunta ou problema?

Seu comentário não fornece informações suficientes para diagnosticar seu problema.

Para sua informação: recebi este erro por causa da extensão do Chrome ng-inspector for AngularJS (extensão angular 1 alternativa ao batarang)

Isso é loucura! Depois de ler todo o tópico, o que corrigiu o problema no modo de desenvolvimento foi desabilitar o ng-inspector para AngularJS, como diz @ KarlGustav-unimicro.

Com isso dito, ChangeDetectorRef.detectChanges() também funcionou para mim, mas me senti realmente maluco.

@ pkozlowski-opensource,
ainda não tenho ideia de por que indicatorStyle() será invocado quando uma das entradas muda,
você pode dar mais explicações?
Se eu implementar ngDoCheck no _componente da barra de progresso_ sem definir ChangeDetectionStrategy.OnPush no componente pai,
descobri que ngDoCheck execução duas vezes,
eu sei porque o primeiro será executado,
mas estou realmente confuso sobre o segundo ngDoCheck ...

http://plnkr.co/edit/myX2Alx9jie2q0FDIME7?p=preview

@LiTiang ,

eu ainda não tenho ideia de por que o indicadorStyle () será chamado quando uma das mudanças de entrada,
você pode dar mais explicações?

Como indicatorStyle() está vinculado a [ngStyle] na visualização, ele sempre será chamado quando o detector de alterações for executado. Isso acontecerá independentemente de as entradas terem realmente mudado ou não.

descobri que a execução do ngDoCheck duas vezes,
eu sei porque o primeiro será executado,
mas estou realmente confuso sobre o segundo ngDoCheck ...

Provavelmente, isso ocorre porque, conforme mencionado anteriormente neste tópico, a detecção de alterações sempre é executada duas vezes no modo de desenvolvimento. Ele faz isso para verificar se não temos código que altera os vínculos durante a detecção de alterações, o que pode causar bugs difíceis na produção.

Uma variação de setTimeout ()

ATUALIZAÇÃO: a CPU ficou 100% maluca sem comparação companionHeightLast: As atualizações da AFAIK estavam se tornando recursivas!

ATUALIZAÇÃO2: Exemplo de êmbolo

Eu queria que a altura de um bloco <ul> dinâmico controlasse a altura de um <img> que vinculei a "companionHeight".

Tão mal ... Mas o seguinte funciona usando um Observable.

Aqui está o elemento <ul> cuja altura está sendo monitorada:

<ul class="title-list-ul" #listul (window:resize)="setCompanionHeight(listul)">

Aqui está o elemento <img> sendo controlado:

<img class="title-list-companion-img" [src]="getCompanionImageURL()" [height]="companionHeight"/>

Aqui estão os métodos de componentes que interagem:

import { Component, OnInit, AfterViewChecked, ElementRef } from '@angular/core';  // redacted
import { Observable } from 'rxjs';

@Component({
  selector: 'resume-title-list',
  templateUrl: './title-list.component.html',
  styleUrls: ['./title-list.component.scss']
})
export class TitleListComponent implements OnInit, AfterViewChecked {

  private error: Object;
  private companionHeight: number = 0;
  private companionHeightLast: number = 0;

   // Lots of irrelevant stuff like ngInit redacted for simplicity.

  constructor(private elementRef: ElementRef) { }  // redacted, mine is more complicated.

  setCompanionHeight(listElement: any) {
    let clientRect = listElement.getBoundingClientRect();
    if (clientRect) {
      this.companionHeight = clientRect["height"];
    }
  }

  // window::resize only happens when the window is resized: This is an initialization 
  // function that sets the initial size of the image... Without it the image height is 
  // initially zero and the image is not shown. 
  // The height was not correct in ngAfterViewInit, so I used ngAfterViewChecked instead.

  ngAfterViewChecked() {
    let ularray = this.elementRef.nativeElement.getElementsByClassName("title-list-ul");
    if (ularray && ularray.length > 0) {
        let h = ularray[0].getBoundingClientRect().height;
        if (h && h != this.companionHeightLast) {
          this.companionHeightLast = h;
          Observable
          .of(h)
          .delay(10)
          .subscribe(h => this.companionHeight = h,
                     error => this.error = error);
        }
    }
  }
}

Comentários sobre problemas fechados podem não ser lidos pelos membros da equipe Angular.
Que tal postar uma pergunta em um desses canais CONTRIBUINDO - Tem uma pergunta ou problema? com um Plunker para reproduzir?

Eu tive o mesmo problema com:

<div *ngIf="isLoading">
   <app-some-viewchild></app-some-viewchild>
</div>

Usar [oculto] em vez de * ngSe resolver o problema.

Eu conheci esse problema também. Finalmente, descobri que o objeto de inicialização padrão é o mesmo que o objeto ngModle.

definir o changeDetection: ChangeDetectionStrategy.OnPush no decorador @Component corrigiu para mim

@elvismercado obrigado, resolve meu problema no 2.1.1!

Eu tinha um componente filho que dependia de um valor passado pelo modelo pai, com o modelo filho lançando essa exceção quando o valor pai mudava. Adicionar sua sugestão ao componente filho faz com que a detecção de alterações não seja executada até que o valor alterado seja enviado ao componente filho, evitando que a detecção seja executada prematuramente.

Se eu tiver uma entrada com foco e removê-la do DOM (condição ngIf), ocorrerá o erro "A expressão foi alterada após ter sido verificada" (somente se a entrada tiver um grupo de formulários associado).
Aqui está um plunker com o problema:
https://plnkr.co/edit/dooRvC1gY1WEcaNdshoP?p=preview
Obrigado!

Então, qual é a solução aqui?

Alterar qualquer valor de entrada em ngOnInit irá acionar isso.

@coli
apenas enrole em

setTimeout(()=>{
 ///your code here
}, 1);

Eu tenho uma combinação de componentes filhos que precisam ser pré-carregados quando um usuário deseja editar uma entidade existente.
Tenho lutado com esse problema por horas até que consegui corrigi-lo usando a postagem @drewlio acima.

Inject _changeDetectionRef:

    constructor(
        private _changeDetectionRef: ChangeDetectorRef) {
    }

E então, logo após fazer sua mudança, chame detectchanges.
Isso funcionou para mim.

    setSizeFromCtrl() {
        console.log("setSizeFromCtrl");
        if (this.sizeFromList && this.tradeProfile && this.tradeProfile.SizeFrom && this.sizeFromCtrl) {
            this.sizeFromCtrl.select(String(this.tradeProfile.SizeFrom));
            this._changeDetectionRef.detectChanges();
            console.log("setSizeFromCtrl DONE");
        }
    }

    setCentreTypeCtrl() {
        console.log("setCentreTypeCtrl");
        if (this.centreTypeList && this.tradeProfile && this.tradeProfile.centreTypeList && this.centreTypeCtrl) {

            for (let i of this.tradeProfile.centreTypeList) {
                this.centreTypeCtrl.select(i.value);
            }
            this._changeDetectionRef.detectChanges();
            console.log("centreTypeCtrl DONE");
        }
    }


Observe que eu tive o mesmo problema, mas uma causa diferente (semelhante?) E soluções diferentes.

  • Nosso aplicativo Angular - https://github.com/GeoscienceAustralia/GNSS-Site-Manager , tem formas reativas de modelo que são aninhadas e construídas em vários componentes em ngOnInit() . Alguns desses formulários são recolhidos com um ngIf no modelo
  • Os dados são lidos também em um ngOnInit() e estavam sendo aplicados com um theModelForm.patchValue(data)
  • Este erro estava aparecendo quando um dos formulários recolhidos foi expandido. Está relacionado ao fato de que o DOM não foi construído porque o formulário foi criado no ngOnInit() que não disparou até ser expandido. Retire patchValue() e o problema foi embora
  • Nós encontramos duas soluções
  • Antes de patchValue() execute um this._changeDetectionRef.detectChanges(); . E altere ngIf para [hidden] para que o formulário e o DOM sejam totalmente construídos. A desvantagem disso é o custo de tempo e memória conforme o formulário completo e o DOM relacionado são criados (isso pode não ser um problema em muitos aplicativos, mas era para nós, pois temos um formulário gigantesco).
  • A melhor solução é aplicar o patchValue() (ou setValue() se os dados e campos forem 1: 1) nos componentes e assim só acontecerá quando o formulário for criado em ngOnInit() .

Não efetuei essas alterações ainda (22/3/17).

Portanto, não acho que essa decisão salvará a todos.
Mas para mim a ocorrência do erro dado foi acompanhada pela criação de um novo elemento de uma classe. Em seguida, adicione-o ao array, que é gerado via * ngFor.
Resolvi esse problema adicionando um construtor à minha classe, que preencheu os campos necessários para exibir no modelo os valores padrão (zeros, linhas vazias)

export class Task {
    task_id: number;
....
    constructor() {
        this.task_name = '';
        this.task_desc = '';
        this.task_percent = 0;
  addNewTask():void{
    let newTask = new Task();
    this.tasksList.push(newTask);
  }

task_name & task_desc & task_percent Estou exibindo no modelo. Se pelo menos um dos campos listados não for inicializado no construtor, recebo um erro semelhante.

+1

Trabalho da solução AerisG222

constructor(private _changeDetectionRef : ChangeDetectorRef) { }

ngAfterViewInit() : void {
    // your code

    this._changeDetectionRef.detectChanges();
}

this._changeDetectionRef.detectChanges () funciona, mas vai causar outros problemas no meu caso. Eu apenas envolvo o código dentro da função setTimeout (), ele resolve.

@GuofuHuang fazer isso é uma forma de evitar o problema e não corrigi-lo, o que às vezes pode levar a ciclos infinitos de Detecção de Mudança

@Toxicable Desculpe, provavelmente não deixei claro, não estou usando this._changeDetectionRef.detectChanges (); Em vez disso, envolvo meu código-fonte em setTimeout ().

@GuofuHuang se tudo o que você colocar dentro de setTimeout causa um CD e você está executando isso em um gancho de ciclo de vida, então é possível que você esteja causando ciclos infinitos de CD. A solução é não fazer alterações que causam o CD durante a execução do CD

@Toxicable Até eu defini-lo como 0?

@GuofuHuang se definir para 0 causa um CD, então sim

@Toxicable Acabei de encontrar este link, http://stackoverflow.com/questions/779379/why-is-settimeoutfn-0-sometimes-useful , ele diz que setTimeout de 0 é algo como pause / yield em C, I don ' Não sei se vai causar algum CD, mas agora funciona perfeito no meu. Se não é esta solução, você tem uma melhor para resolver este problema?

@GuofuHuang Eu não sei o que pausa / rendimento faz em C, mas em JS isso colocará o retorno de chamada no final da fila de eventos. Minha solução é a anterior: A solução não é fazer alterações que causam o CD durante a execução do CD

settimeout é a solução
Você não precisa especificar o parâmetro ms e vou esperar um tique

@ zigzag95 @GuofuHuang veja este exemplo de por que setTimeout não é a solução
https://plnkr.co/edit/dv8K9EvVQLG59Gxsl3oI?p=preview

@Toxicable Obrigado, mas meu caso é muito diferente deste, e não vejo nenhum loop infinito. Mas este é definitivamente um bom exemplo que me ajuda a entender mais o angular.

@GuofuHuang De fato, não vai acontecer no seu caso porque você está fazendo isso em ngAfterViewInit que é chamado apenas uma vez. Meu ponto é que é possível causar um loop infinito com esse método, portanto, é perigoso usá-lo. Isso é o que o plunkr está mostrando.

@moutono Seus truques me ajudaram! Muito obrigado 😄

Como o problema é sobre como acionar uma detecção de mudança, resolver uma promessa também pode funcionar porque os patches de macaco do ngZone também prometem. Este funcionou para mim:

ngAfterViewInit() {
  Promise.resolve().then(() => your_code_here);
}

Sim, setTimeout funciona, mas eu não gostei dessa correção, no meu caso foi causado porque eu estava mudando o valor em um EventEmitter
A solução foi a mudança
private generalSubscriber: EventEmitter<any> = new EventEmitter<any>();
para
private generalSubscriber: EventEmitter<any> = new EventEmitter<any>(true);

estranho né?
Bem, isso significa que o emissor de eventos é assíncrono
https://angular.io/docs/ts/latest/api/core/index/EventEmitter-class.html

Há alguma solução para isso? Por que está fechado?

Eu tenho que limpar o cache todas as vezes

no meu caso, eu estava substituindo um esboço de imagem no carregamento da imagem, tive que colocá-lo em um setTimeout

@intergleam @ wasa4587 @ caroso1222 @tandu @ AerisG222 @ chamou-moore @robwormald @ svi3c @ pkozlowski-opensource @pcroc @zoechi @stefankoru @bennadel @bryanforbes @Necroskillz @drewlio @ElsewhereGames @zoechi @ user414 @ e-oz

É um erro enfrentando durante o desenvolvimento. No servidor de produção funcionando bem.

@smartHasmukh é um erro apenas do modo de desenvolvimento, portanto, nenhuma surpresa.
Você ainda deve consertar.

Se esse erro ocorrer, provavelmente você interromperá o fluxo de dados de uma direção. O que poderia ser algo como alterar os dados de um componente do irmão, alterar os dados dos pais nos ganchos do ciclo de vida dos filhos, talvez mais alguma coisa.
Essa exceção lançada não é um erro, mas o auxiliar para o desenvolvedor entender que o contrato de fluxo de dados de uma direção foi quebrado de alguma forma. O fato de que isso funciona na produção é acidental, você deve revisar como está alterando seus dados na comunicação entre pais e filhos e corrigi-los no modo de desenvolvimento.

@smartHasmukh Eu costumava achar isso desconfortável também. Por exemplo, eu me conecto aos eventos de navegação e emito um evento ao componente principal para mostrar um carregador. E em cada componente eu oculto esse carregador, depois de receber os dados do servidor (então, dentro de uma assinatura). Isso é bom. Mas, em um componente, obtive apenas alguns dados de uma fonte "estática", nenhum observável lá, então simplesmente tentei usar o ngOnInit para dizer ao componente principal para ocultar o carregador. Então eu entendi o erro, é claro.

Mesmo que meu caso deva ser uma coisa simples, não é a maneira certa de fazer isso. Eu tive que tomar a decisão de não mostrar o carregador em primeiro lugar, para aquele componente (o que poderia ficar mais complicado se eu tivesse mais componentes como esse) ... Ou, também, esconder o carregador do meu serviço de dados , em vez de no nível do componente. Ou, uma solução feia, seria envolver aquele caso específico em um setTimeout (). Porque a abordagem inicial não foi a certa.

TL / DR:
Tenho certeza de que deve haver uma maneira adequada para o seu cenário também, diferente de uma correção _setTimeout () _ feia (que _sis_mente_ escolhi naquele momento, mas, novamente, é um cenário muito simples e eu sei o que é acontecendo lá - ainda, posso ter que alterá-lo em algum ponto, em uma versão futura).
Você pode tentar StackOverflow para seu caso específico, dê mais detalhes. Tem que haver uma maneira.

Claro, obrigado @MrCroft @tytskyi e eu farei isso, Sr. @zoechi e eu sei. Não é nenhuma surpresa. mas estou apenas avisando. nada mais

@tytskyi

O fato de que isso funciona na produção é por acidente, você deve revisar

Não, na maioria dos casos, minha resposta a esse erro é "sim, eu sei e é intencional". Muitos componentes em meus aplicativos estão carregando algo após o init e depois de receber novos valores em variáveis ​​associadas. Essa questão é apenas "feiúra conhecida" do Angular e ninguém liga.

@ e-oz se você está afetando de alguma forma o estado dos pais ou irmãos em qualquer um dos ganchos do ciclo de vida, então isso é a quebra do fluxo de dados em uma direção. Você deve fazer essas alterações quando o estado do aplicativo estiver estabilizado, mas não no meio da detecção de alterações. É por isso que existem aqueles truques com microtarefa, setTimeout 0 etc.

@tytskyi acalme-se com o seu "deveria", estou fazendo alterações após a estabilização - é óbvio se ler com atenção - a solicitação de http para carregar dados adicionais irá, obviamente, levar mais tempo do que a estabilização inicial. Você não vai me convencer de que esse comportamento do Angular é correto, nem tente.

@ e-oz como isso está relacionado a uma solicitação HTTP. Uma resposta de solicitação HTTP causa a detecção de alterações e você não obterá o erro "A expressão foi alterada ...".
Você pode fornecer mais informações?

@zoechi não há motivo para perder tempo com isso, ninguém vai mudar nada, a tarefa está encerrada.

@ e-oz o problema foi encerrado há um ano e a equipe Angular tinha prioridades bem diferentes na época (lançar um release) e esse problema não era um bloqueador na época.
Se você acha que tem um caso válido, deve criar um novo problema.

@zoechi Acho que você não vai decidir o que devo fazer. Posso criar um novo problema, mas não preciso. Com todo o respeito, não gosto desse tom de "você deveria".

@ e-oz Eu vejo, seus comentários são apenas para desabafar sua frustração e você não está interessado em obter uma solução. Por favor, pare de desperdiçar o tempo de outras pessoas aqui com seus comentários inúteis.

se você estiver ligando para http, inscreva-se em seu componente, basta adicionar ..
Promise.resolve().then(() => your_code_here);
ou
myObservable.delay(10).subscribe(...)

Uma das duas soluções resolverá seu problema

@vicb Pare de fechar problemas que não foram corrigidos. Por que você está fazendo isso ?

Pelo menos sugira alguma correção adequada, mas fechar isso é inaceitável

@diegogarciaa ... e o que exatamente não está consertado ou está errado do seu ponto de vista? A conversa ^^^ é tão longa que é difícil encontrar o núcleo real.

@ mlc-mlapis com todo o respeito, não sou seu professor, se você não consegue ler ou entender o problema, pare de se preocupar. Passei longos minutos lendo todo o conteúdo, recomendo o mesmo.

A atitude da equipe angular (não toda equipe, mas quem está aqui encerrando essa questão) parece tão empreendedora: Não bloquear (meu salário), não consertar tão cedo.

@diegogarciaa ... muito bom. Continue como acima e você será bem-vindo em qualquer lugar.

@ mlc-mlapis Não quero ser bem-vindo onde as pessoas não podem ler e tentar mentir onde não deveriam.

@diegogarciaa ... Só pensei que você pessoalmente tem um problema e parece que agora não é verdade. E a realidade também é que a maioria dos problemas com Expression has changed after it was checked ... não são bugs, mas simplesmente não entendem direito como o CD funciona.

@ mlc-mlapis ok ... vamos entender

http://plnkr.co/edit/nm8OkrpZCIp4cvA6TbpO?p=preview

Neste plunk posso entender que a variável foi ligada e verificada quando ngAfterViewInit foi chamado, portanto, quando ele recebe um novo valor, e não aciona uma nova rodada de verificação, as exceções são lançadas

Mas, por exemplo, se eu tiver um view container ref ... e uso, por exemplo:

this.service.GetData (). subscribe (
resposta => this.component.instance.dataModel = resposta
);

Considere que dataModel está sendo usado como {{dataModel.Field}} em meu html

this.component é um componente dinâmico sendo carregado em determinados eventos, como evitar o erro? Qual seria a maneira correta de passar os dados para o meu componente antes dos ganchos da bicicleta de detecção de mudança

@diegogarciaa ... sim, este é um exemplo típico onde operações assíncronas e sincronizadas são misturadas e se encontram em um CD e sua confirmação no modo dev. Não vou repetir a explicação do post https://hackernoon.com/everything-you-need-to-know-about-the-expressionchangedafterithasbeencheckederror-error-e3fd9ce7dbb4 , então talvez tente ler primeiro.

E veja também https://hackernoon.com/here-is-how-to-get-viewcontainerref-before-viewchild-query-is-evaluated-f649e51315fb.

Portanto, o artigo basicamente diz que devo chamar manualmente uma rodada de detecção de alterações ...

Vamos ser honestos, estou muito chateado com o estado atual ... até as coisas mínimas no angular são tão chatas e cansativas ... eu não consigo nem respirar. Foda-se

@diegogarciaa ... não, é apenas uma solução auxiliar. Você também pode usar promise.then ou usar setTimeout ... mas a solução recomendada neste caso é provavelmente um serviço compartilhado, então você não atualizará diretamente a propriedade do componente dinâmico cruzando o ciclo do CD e seu confirmação.

Ou apenas crie uma instância do componente dinâmico no momento em que você tiver os dados. Portanto, sua assinatura invocará a criação da instância do componente dinâmico.

Mas o que é importante -> a lógica primária por que o erro acontece -> porque as mudanças unidirecionais devem fluir sempre de cima para baixo em toda a árvore e após um ciclo de CD há uma confirmação do status de que o princípio unidirecional foi respeitado.

Esse "foda-se" não era pessoal ... apenas desabafando minhas frustrações.

Usamos um esquema de diretiva para lidar com nossos componentes. Nós construímos um helper que carrega um componente em uma referência de visualização de componente, e como entendemos, os dados devem estar disponíveis quando um componente está sendo carregado

protected loadPartialView(viewName: string, target: ViewContainerRef) : ComponentRef<any> {
        const factories = Array.from(this.resolver['_factories'].keys());
        const factoryClass = <Type<any>>factories.find((x: any) => x.name === viewName);
        const factory = this.resolver.resolveComponentFactory(factoryClass);
        return target.createComponent(factory);
}

No exemplo acima: Eu gostaria de fazer algo assim:

return target.createComponent(factory, dataSource);

Onde minha fonte de dados estaria disponível na hora do construtor

Assim como o redux, que usa um objeto para manipular a fonte de dados que passa pelos componentes, estamos pensando em implementar um componente injetável que manipule os dados para nós, para que possamos obtê-lo antes que a bicicleta seja engatada.

Diegogarciaa

Não acho que os dados devam estar disponíveis antes ... um componente dinâmico ainda é um componente com @Input() e @Output() mas a questão é quando você mudará os dados.

... os dados devem estar disponíveis quando um componente está sendo carregado ...

Suponho que você também precise usar componentes de módulos carregados lentamente, então eu uso um mapa diretamente em um módulo para ter a possibilidade de acessar componentes usando apenas nomes de string.

export default class LazyLoadedModule {
    cmps: Map<{}, {}> = new Map();
    constructor() {
        this.cmps.set('first-component', FirstComponent);
        ...
    }
}

O que return target.createComponent(factory, dataSource); deve significar? Porque a API real é createComponent(componentFactory, index, injector, projectableNodes, ngModule) .

E talvez o novo módulo @ angular / cdk seja interessante para você. Basta introduzir aqui: https://medium.com/@caroso1222/a -first-look-into-the-angular-cdk-67e68807ed9b.

Se valer a pena e se puder ajudar alguém, em vez de usar setTimeout e como usar ChangeDetectorRef.detectChanges() não funcionou para mim, acabei usando NgZone.onStable e executei meu código inscrevendo-se uma vez no EventEmitter ...

constructor(
  private zone: NgZone,
) { }

ngAfterViewInit() {
  this.zone.onStable.first().subscribe(() => {
    // your code here
  });
}

Não estou totalmente ciente das consequências de fazer isso, mas pode ser pior do que usar setTimeout ? Se alguém tiver algum comentário sobre esse assunto, será muito bem-vindo!

A solução

constructor(private _changeDetectionRef : ChangeDetectorRef) { }

ngAfterViewChecked() : void {
    // your code
    this._changeDetectionRef.detectChanges();
}

este é o componente html:

{{lastData.note [i] .date | data: 'dd.MM.aaaa'}} | {{lastData.note [i] .date | data: 'HH: mm'}}:# BFL15_200817 | {{lastData.status.name}} por {{lastData.note [i] .admin}}

Recebi o erro se os dados na matriz forem mais de um, alguma solução?

Este é certamente um problema complexo, mas para alguns casos (especialmente quando você está modificando propriedades em um ContentChild) pode ser resolvido movendo a lógica para ngAfterContentInit () em vez de ngAfterViewInit () ou ngOnInit ()

É incrível como coisas simples podem causar tanta confusão em

Não se preocupe, todo mundo percebeu também 😕
image

@jakeNiemiec trabalho coxo, troll, ninguém está mais procurando Angularjs
https://trends.google.com/trends/explore?date=all&q=Angular%20tutorial , React% 20tutorial
image

Sim, eu esperaria que mais pessoas precisassem pesquisar no Google "tutorial angular" por desespero, daí aquele comentário inicial sobre "confusão".

Mas não se preocupe, podemos verificar o npm para obter as estatísticas de uso exatas: http://www.npmtrends.com/react-vs-@angular/cli -vs-vue-vs- @ angular / core
image
image

Basta comparar a quantidade de edições. Eu realmente gostaria de ver o angular melhorar, mas suspeito que o Vue.js irá superá-lo em um futuro distante. Tendo programado em todos os 3, eu recomendo fortemente o Vue para os desenvolvedores do angular. É como angular sem o clichê.

ok resposta aceita, estou perfeitamente bem com essas estatísticas.
Imagino que haja mais pessoas usando PHP na Índia do que Java em todo o mundo. Seria um idiota usar PHP para um aplicativo corporativo em grande escala, então você deve usar seu próprio cérebro às vezes, a vida será melhor

@jakeNiemiec ... 50% dos problemas que estão sendo criados estão erroneamente colocados lá ... eles são problemas de suporte / conhecimento na verdade e não deveriam estar lá. A diversão é que a maioria dos tópicos necessários está muito bem documentada nos documentos oficiais + as respostas são baseadas no conhecimento de JavaScript. Mas você sabe, as pessoas não leem os documentos com profundidade suficiente.

@HostBinding pode ser uma fonte confusa desse erro.

Considere uma ligação simples em um componente, como @HostBinding('style.background') .

Essa propriedade é verificada pela detecção de alteração do componente * pai * como se fosse o proprietário dele. De nossa perspectiva, queremos pensar nele como o componente filho 'possuindo' essa propriedade.

Portanto, parece que deve haver uma maneira de um componente excluir propriedades para verificação neste caso? Ou é mais complicado do que isso?

Eu tive que fazer meu componente pai executar detectChanges (ou adicionar um div extra no filho) para evitar o erro no caso em que o componente filho estava simplesmente mudando sua própria cor de fundo (e nunca fazendo isso em nenhum outro lugar) .

Descrição mais completa: https://stackoverflow.com/questions/43375532/expressionchangedafterithasbeencheckederror-explained/51662105#51662105

Você só precisa fazer algo, qualquer coisa, que acione outra rodada de detecção de alterações durante esse método - emitir um evento, seja o que for. Envolvê-lo em um tempo limite (flashback da fila para ng1 :-P) é uma maneira que funcionaria, mas parece muito confuso para mim no ng2.

No angular 4, isso funciona 4 me <3

Este problema foi bloqueado automaticamente devido à inatividade.
Registre um novo problema se você estiver encontrando um problema semelhante ou relacionado.

Leia mais sobre nossa política de bloqueio automático de conversas .

_Esta ação foi executada automaticamente por um bot._

Esta página foi útil?
0 / 5 - 0 avaliações