Solucionado (ver solução)
Solucionado
(ver solução)
4
respostas

Subject Next

Estou com dúvidas quanto ao uso do subject em uma aplicação pessoal. Tentei usar ele e até funciona em partes. Mas, quando faz o next em app.component ele simplesmente ignora o resultado. E pega o valor que passei no startwith;

código do subject

@Injectable({
  providedIn: 'root'
})
export class HeaderNavbarService {
  displayNavSubject: Subject<boolean> = new Subject<boolean>();

  getDisplay() {
    return this.displayNavSubject.asObservable().pipe(startWith(false));
  }

  disableMenu(display: boolean) {
    console.log(display);
    this.displayNavSubject.next(display);
  }
}

código no componente

@Component({
  selector: 'app-header-navbar',
  templateUrl: './header-navbar.component.html',
  styleUrls: ['./header-navbar.component.css']
})
export class HeaderNavbarComponent implements OnInit {
  disableMenu$: Observable<boolean>;

  constructor(private headerNavService: HeaderNavbarService) { }

  ngOnInit() {
    this.headerNavService.getDisplay().subscribe(resultado => console.log(resultado));
    this.disableMenu$ = this.headerNavService.getDisplay();
  }
}

Código Header HTML

<app-header-login-nf [isDisableMenu]="disableMenu$ | async"></app-header-login-nf>
<p>{{disableMenu$ | async}}</p>

Código no app component

import {Component, OnInit} from '@angular/core';
import {HeaderNavbarService} from './components/header-navbar/header-navbar.service';

@Component({
  selector: 'app-root',
  templateUrl: './app.component.html',
  styleUrls: ['./app.component.css']
})
export class AppComponent implements OnInit {
  constructor(private headerNavService: HeaderNavbarService) {
  }

  ngOnInit(): void {
    this.headerNavService.disableMenu(true);
  }
}

App HTML

<app-header-navbar></app-header-navbar>

no console quando chamo o disableMenu no onInit do appComponent ele fica true; Mas quando faz o |async no headerComponent ele está falso no console.

4 respostas

achei uma solução. Mas, não consegui compreender. Tive que usar o setTimeout no next

ngOnInit(): void {
    setTimeout(() => this.headerNavService.disableMenu(true), 0);
  }

Aí funcionou. Conseguiria dar uma explicação? Por gentileza Flavio. Obrigado desde já.

Bom dia!

Dei uma olhada no seu código e tem algo que pode dar problema. Veja esse trecho:

 getDisplay() {
    return this.displayNavSubject.asObservable().pipe(startWith(false));
  }

Para cada chamada de getDisplay() você esta retornando um novo Observable que emitirá falso por padrão. A cada chamada será um novo Observable que emitirá false. Nesse sentido, você precisará guardar o retorno de getAsObservable em uma propriedade do seu serviço e retornar o mesmo observable a cada chamada, algo assim:

export class HeaderNavbarService {
  displayNavSubject: Subject<boolean> = new Subject<boolean>();
  display$: Observable<boolean>;

  constructor() {
     // na inicialização guarda um observable que será o mesmo tem todos os lugares que ao ser acessado pela primeira vez emitirá false como valor.
      this.display$ = this.this.displayNavSubject.asObservable().pipe(startWith(false))
  }

  getDisplay() {
   // retorna o mesmo observable
    return this.display$;
  }

  disableMenu(display: boolean) {
    console.log(display);
    this.displayNavSubject.next(display);
  }
}

Se não funcionar, verifique se não é aquele caso que ensino no curso de usar um BehaviorSubject.

No aguardo!

solução!

Não deu certo. Com BehaviorSubject deu certo.

Ou assim pra subject deu também.

ngOnInit(): void {
    setTimeout(() => this.headerNavService.disableMenu(true), 0);
  }

Obrigado Flavio

Excelente! Então, prefira ir de BehavioSubject do que o hack do setTimeout. Além disso, não deixa de alterar aquelas chamadas de getAsObservable que retorna um observable novo a cada chamada. Não é necessário.

Sucesso e bom estudo meu aluno!