Angular4 ExpressionChangedAfterItHasBeenCheckedError using recursive method

0

I'm trying to develop a chat that sends several messages, and when an interaction is needed, that they display buttons or a textbox. This chat displays typed messages ...

But I have a problem with the cycle to send messages in a row ...

I have a component chat.component.ts that loads text in a span with "typing" effect.

Typed.ts

I ended up creating my own recursive Typing method, as I found several on the internet, but I would need to adapt them, mainly to find out when the method was finished ...

export default class Typed {
  public posicao:number = 0
  public complete : boolean = false

  typeWriter(element: string, txt: string, speed: number,) {   
    var that = this
    let intervaloVirgula: number = 500
    let intervaloPonto: number = 1000

    if (this.posicao < txt.length) {
        document.getElementById(element).innerHTML += txt.charAt(this.posicao);
        this.posicao++;

        let strNaPosicao = txt.charAt(this.posicao - 1)

        switch (strNaPosicao) {
            case '.':
                setTimeout(function () { that.typeWriter(element, txt, speed) }, speed + intervaloPonto);
                break;
            case ',':
                setTimeout(function () { that.typeWriter(element, txt, speed) }, speed + intervaloVirgula);
                break;
            default:
                setTimeout(function () { that.typeWriter(element, txt, speed) }, speed);
                break;
        }           
    }
    else{
        this.complete = true
    }
  }
}

The variable this.complete is bound to an ngIf, and when the method terminates it will become true, thus displaying the BootComponent component.

<app-botao-decisao
  [historiaObjeto]="historiaObjeto"
  [montarInteracao]="typed.complete"
  (ClicarBotaoResposta)="ClicarBotaoResposta($event)">
</app-botao-decisao>

Classe BotaoDecisao.ts

This component is displayed and fired where it has a switch for each type of action. In this type, it returns to the component itself through an EventEmitter method that will call the method checkProgress of chat.component again.

private MontarInteracaoHistoria(){

  switch(this.historiaObjeto.tipo){
    case("chat"):
      //proxima historia
      this.verificaProgresso(this.historiaObjeto.proximapergunta)

      break;
  }
}

public verificaProgresso(idProximaHistoria :string) {
  this.ClicarBotaoResposta.emit(idProximaHistoria)
}

Class Chat.Component

Now returning to the component chat.componente, the call of the method of typewriter is carried out and at that moment I have an error of the Angular ...

public ClicarBotaoResposta($event){   
  // $event pega o parametro do emitter
  let idProximaHistoria: string = $event

  //incrementa contagem de frases
  this.progresso++

  //Carrega as linhas com typed passando parametros
  this.CarregarHistorias(idProximaHistoria,this.typeSpeed)
}


private CarregarHistorias(idProximaHistoria: string, speed: number){
  // Cria objeto que faz efeito de escrita
  this.typed = new Typed()

  //retorna objeto do tipo HistoriaModel com as propriedades
  this.historiaObjeto = this.RecuperaHistoria(idProximaHistoria)

  //Incrementa mais objetos <span> no array para aparecer no HTML
  if (this.progresso != 0)
  {
    this.spansCont.push("typed"+ this.progresso)
  }

  setTimeout(()=>this.typed.typeWriter('typed' + this.progresso, this.historiaObjeto.frase, speed),500)
}

It says that this.complete property of the Typed object has been changed before being checked and can not follow and send the message sequence ...

I tried to use promises for the Typed method to be asynchronous, but this method typed.typewriter that I call is recursive and I could not implement it.

I do not know if I could explain very well, but if anyone can help and give the structure / code suggestions to have good practices and a better operation, I would appreciate it!

    
asked by anonymous 08.03.2018 / 20:09

0 answers