Tengo un formulario de página con valores ya establecidos, elementos de botón anterior y siguiente.
En ngOnInit, obtengo una Lista con 3 elementos de un observable , como valor inicial; a veces obtengo 4 elementos .
Antes de ir a la página siguiente, tengo que hacer clic, necesariamente , en un botón que llamará a la función de calculate() que hará una solicitud y mi Lista observable tendrá 4 elementos.
Entonces, cuando hago clic en el botón siguiente en onNextButton() , me gustaría usar el valor inicial para compararlo con el actual, si son iguales, o verificar si esta lista tuvo algún cambio (cualquier incremento).
De la forma en que lo estoy haciendo, no puedo mantener/almacenar el primer valor. Al hacer clic en el siguiente botón, obtengo el valor actualizado, en lugar del anterior.
Mi código:
export class PageComponent implements OnInit { questions$: Observable<any[]>; hasChange: boolean; ngOnInit() { // GETTING INITIAL VALUE this.questions$.subscribe((quest: any[]) => { this.hasChange = quest.length > 3 ? true : false }); } calculate() { // calling a request // at this point, my observable will update and will have 4 items. } onNextButton() { if (hasChange) { // submit() } else { // navigate() } } }Entonces, en este escenario, el valor inicial debería ser una lista con 3 elementos, pero obtengo 4 y está rompiendo mi lógica...
¿Cómo obtengo el valor anterior de Observable y lo almaceno en una variable? O, ¿cómo puedo detectar cualquier cambio?
Probé el tema de behavioursubject y pairwise de RxJS, pero no estoy seguro de cómo aplicarlo.
¡¡¡Gracias!!!
Como dijiste, debes usar ReplaySubject o BehaviourSubject, ya que Observable no tiene esa "memoria" para recuperar el último valor emitido. ReplaySubject y BehaviourSubject son similares, ambos envían el último valor emitido en la suscripción, pero ReplaySubject solo emite el último valor emitido en la suscripción y BehaviourSubject almacena una lista de los últimos valores emitidos (tamaño configurable). Usaré BehavoiurSubject ya que es un poco más completo.
Simplemente reemplace el Observable que estaba usando con BehaviourSubject, y tenga en cuenta que debe definir ese tamaño de memoria cuando instancia la clase. Por ejemplo, podría crear un método que devuelva un BehaviourSubject con el último valor booleano almacenado de esta manera:
private fooBehaviourSubject; function ngOnInit: void{ this.fooBehaviourSubject = new BehaviorSubject<boolean>(1); // 1 is the "stack" size this.fooBehaviourSubject.next(true); // <- First value emitted here } function getValue: BehaviourSubject<boolean> { return this.fooBehaviourSubject; }Cuando te suscribes así:
getValue().subscribe(e => console.log(e))el último valor almacenado (verdadero) se recuperará automáticamente y se mostrará en la consola, pero asegúrese de haber emitido al menos uno primero, o no ejecutará la suscripción hasta que se llame al siguiente método. Después de eso, cada actualización del valor activará ese archivo console.log con el valor actualizado.
Aplicado a su código, podría crear BehaviourSubject en ngOnInit, suscribirse a él también en ngOnInit para definir el evento de devolución de llamada y llamar al siguiente método de BehaviourSubject una vez que la lista deba actualizarse.
export class PageComponent implements OnInit { questions$: Observable<any[]> hasChange: boolean ngOnInit() { // GETTING INITIAL VALUE let hasSome = false this.questions$ .subscribe((quest: any[]) => { // ### This is works for me! hasSome = quest.some(item => item.id === 'whatever') // ### This is the way that I was trying to do. // ### Is's not wrong but didn't work for me =( // this.hasChange = quest.some(item => item.id === 'whatever') ) this.hasChange = hasSome } calculate() { // calling a request // at this point, my observable will update and will have 4 items. } onNextButton() { // ### Now this.hasChange is assigned once and where I want, OnInit. if (this.hasChange) { // submit() } else { // navigate() } } }