How can you set up an Observable to store and return a collection of all previous values each time a new value is added?

Struggling with RxJs Observables and need some assistance. I'm a beginner in working with them.

I am attempting to create an Observable logging stream that serves two purposes:

  1. Push any new line/value written to the log file to the stream.
  2. Begin with pre-populated values from the log file.

I have successfully met both requirements. The current challenge lies in using it with *ngFor.

*ngFor necessitates an array from an Observable for comparison to facilitate adding/removing elements (my assumption). However, my observable only returns an array of the most recently pushed item.

//logviewer.page.ts constructor()
this.logs = Subject.create();
this.logs$ = this.logs.asObservable()
            .startWith("logs\\error.log")
            .flatMap((fileName: string) => {
                //begin by reading the existing log files as a string
                return this.$localStorageService.readAsStringAsync(fileName);
            })
            .map((contents: string) => {
                //splitting the log file line-by-line into a log entry
                let logs = contents.split(/\r\n|\r|\n/).filter(n => n.length > 0);
                logs.forEach((s, ix, parent) => {
                    let x = JSON.parse(s);
                    parent[ix] = { timestamp: new Date(parseFloat(x[0])), message: x[1] };
                })
                return logs; //an array of objects { timestamp, message }
            })
            //merge the existing application log stream
            //throughout the application we log errors, info, etc
            //if a new entry is made it will appear here
            .merge(this.$loggerService.applicationLog$.map((x) => {                    
                //return an array with one object { timestamp, message }
                return [{ timestamp: new Date(parseFloat(x[0])), message: x[1] }];
            }))

The template at present is straightforward.

//logviewer.template.ts
<div *ngFor="let entry of logs$ | async">
    {{entry|json}}
</div>

To test it, I have added a button to insert an entry.

//logviewer.page.ts
addEntry() {
    this.$loggerService.error("this is a test");
}

//LoggerService.service.ts
private applicationLog: ReplaySubject<any[]>;
get applicationLog$(): Observable<any[]> {
    return this.applicationLog.asObservable();
}

error(...args) {
    let data = [Date.now().toString()].concat(args.map<string>((n, ix) => { return toString(n); }));

    //...write to file

    //send through the subject
    this.applicationLog.next(data);
}

Upon clicking addEntry, all components function correctly, and the value navigates through the observable sequence properly. However, *ngFor updates solely with a single value instead of maintaining history of previous log entries, displaying only the last returned array which is reasonable.

How can I ensure my observable sequence always presents an array containing all values? It currently delivers one entry at a time but I need the entire history for *ngFor.

I had misconceptions about *ngFor and the async pipe. Believed that it would automatically subscribe to the observable and add new entries to *ngFor but apparently not.

Answer №1

Consider utilizing the scan operator for this purpose:

this.logs$ = this.logs.asObservable()
        ...
        .merge(this.$loggerService.applicationLog$.map((y) => {                    
            //create an array containing an object with timestamp and message
            return [{ timestamp: new Date(parseFloat(y[0])), message: y[1] }];
        }))
        .scan((accumulator, value) => {
            accumulator.push(...value);
            return accumulator;
        }, []);

Similar questions

If you have not found the answer to your question or you are interested in this topic, then look at other similar questions below or use the search

Is it possible to develop a C equivalent of the typescript Record type?

Is there a way to create a record type equivalent in C like what can be done in TypeScript, and add attributes during runtime? I am aiming to replicate the following: const familyData: string[] = ["paul", "em", "matthias", "kevin"]; const myFamily: Record ...

Is it possible to eliminate the port number in Angular 7?

Currently, I am utilizing Angular in conjunction with an ASP.Net Web application. One interesting observation I've made is that when I use ng build, the app builds and runs on a URL without any port number. However, if I run the app using ng serve, it ...

Retrieving the necessary data from my object to perform a sum calculation in angular

Having trouble retrieving an attribute from an array in my code. In my .ts file, I am fetching data from my backend endpoint like this: export class PostFeedComponent implements OnInit { data: any = {}; constructor(private http: HttpClient) { t ...

The Angular functionality is functioning correctly on Mozilla browsers, but encountering issues on Chrome

I am looking to create a convenient page on my website for my team to easily access and copy the email template I have created to send to clients. The process would involve them visiting this page, clicking a button, and then pasting the email template dir ...

How can I determine the return type for a specific set of parameters in a generic function?

I have a requirement to develop a utility type that can take the signature of a generic function along with its arguments. The goal is to determine the return type of the signature as if it were called with those specific arguments. My initial attempt: ty ...

What is causing me to be unable to concentrate on specific elements when utilizing react refs?

I encountered a strange scenario where I had a collection of references to various form elements like buttons, different types of inputs, and more. I then generated an error summary that, when clicked, automatically focused on the element in question, scro ...

Adjust the icon's color after it has been clicked

How can I make the icon change color after it's clicked in Angular 4 with Bootstrap? I have icons displayed in panels using *ngFor loop and currently, when I click on an icon, it changes color in all panels. How do I make it change color only in the s ...

Tips for hiding a sidebar by clicking away from it in JavaScript

My angular application for small devices has a working sidebar toggling feature, but I want the sidebar to close or hide when clicking anywhere on the page (i.e body). .component.html <nav class="sidebar sidebar-offcanvas active" id="sid ...

What is the best way to set a timeout for an Angular 2+ HTTP request?

Just a typical query appears as follows: this.people = http.get('http://localhost:3000/users') .map(response => response.json()); Is there a method to delay or timeout this? ...

Combine an empty array in JavaScript with the existing array to eliminate the current items

Is there a more effective way to merge arrays and update state based on the array received from the server? The array may be empty, which would result in removing all values from the state individually. My objective is to update a new state depending on t ...

Rearranging data received from an Observable

TL;DR I am working on an Angular app where I need to shuffle an array of names retrieved from a network request and ensure that each group of 6 names selected is unique. However, I noticed duplicates in the selections. Here's a CodePen example using o ...

Employing Typescript types in array notation for objects

Can someone please help me decipher this code snippet I found in a file? I'm completely lost as to what it is trying to accomplish. const user = rowData as NonNullable<ApiResult["getUsers"]["data"][number]["users"]> ...

Leveraging File functionality in TypeScript

In the process of developing a web application with Angular 4 and Typescript, I encountered an issue while attempting to retrieve the date of a file for upload. Specifically, when trying to access the lastModified property of a File object, Typescript retu ...

Editing an object directly within an array in React works seamlessly, however, the process becomes slightly complicated when utilizing

import { useState } from "react"; type Condition = { criteria: string; met: boolean; }; type ConditionComponentProps = { condition: Condition; setCriteria: (criteria: string) => void; setMet: (met: boolean) => void; }; function ...

Encountering an issue with the Link component in Next.js when using TypeScript: The href prop in <Link> should be a string or object, but it is currently undefined

Here is my customized link component code implemented using TypeScript: ... const NavLink: React.FC<{ activeClassName: string; className: string; href: string; clickEvent?: MouseEventHandler; onClick?: MouseEventHandler; title: string; }> ...

The 'undefined' type cannot be assigned to the 'never' type

interface A { name?: string age: number } var a: A = { name: '', age: 23 } var result:A = (Object.keys(a) as Array<keyof A>).reduce((prev, key) => { if (a[key] || a[key] === 0) { prev[key] = a[key] // an error was reporte ...

Issues encountered while developing a ReactJS application using TypeScript

While attempting to create a React app using the command npx create-react-app client-app --use-npm --typescript, I expected to generate a project with TypeScript files, but instead ended up with index.js and app.js rather than index.tsx and app.tsx. Could ...

Diving into Angular2 template forms: unraveling the mysteries of the reset function

After going through the template forms tutorial in Angular2, I'm facing a bit of confusion regarding the behavior of the native reset JavaScript function on Angular2 ngModel. While it's not explicitly clarified in the official documentation, my u ...

Exploring TypeScript Decorators and the Intricacies of Circular Dependencies

Take a look at this code snippet that involves inter-dependent code using decorators. Let's walk through the workflow where the actual classes are passed for later use: The application imports and executes Parent.ts @Test(Child) triggers the import ...

Is it possible for me to distribute one Angular project that can be utilized for both Web and Ionic platforms?

Recently, I successfully developed an Angular 5 project which is now deployed on a webserver and utilized by users. The project includes @angular/material2 and angularfire5. My interest has shifted towards creating mobile applications, and I discovered th ...