How to showcase the data retrieved via BehaviorSubject in Angular

I've been working on retrieving data from an API using a service and passing it to components using BehaviorSubject in order to display it on the screen:

Here is the service code snippet:

@Injectable({
    providedIn: 'root',
})
export class UserService {
    userOnChange: BehaviorSubject<User | null> = new BehaviorSubject<User | null>(null);

    constructor(private api: HttpRequestService) {}

    getCurrentUser() {
        this.api.get<User>('/user/me', new HttpParams()).subscribe({
            next: response => {
                this.userOnChange.next(response.body);
            },
        });
    }
}

And here's a snippet of the component code:

@Component({
    selector: 'app-topbar',
    templateUrl: './topbar.component.html',
    styleUrls: ['./topbar.component.scss'],
})
export class TopbarComponent implements OnInit {
    public user: User | null = new User();

    constructor(
        private authService: AuthService,
        private router: Router,
        public userService: UserService,
    ) {
                this.userService.userOnChange.subscribe({
            next: value => {
                if (value != null) {
                    this.user = value as User;
                    console.log(value.Username);
                    console.log(this.user.Username);
                }
            },
        });
    }

    ngOnInit(): void {

    }
}

Lastly, here's a snippet of the template code:

<span *ngIf="this.user && this.user != null"> user: {{ this.user.Username }}</span>

However, I'm facing issues where the displayed value does not change on the template when the subject emits a new user. Additionally, both console.logs within the subscribe block write 'undefined'. Could you please help me identify what I might be doing wrong?

Answer №1

Make sure to wait for the response body. You can use the following code snippet as a guide (not yet verified):

fetchUserDetails() {
    this.api.get<User>('/user/details', new HttpParams()).subscribe({
        next: async result => {
            this.userInformation.next(await result.body);
        },
    });
}

If the above approach doesn't work and your data is in JSON format, consider using .json instead.

fetchUserDetails() {
    this.api.get<User>('/user/details', new HttpParams()).subscribe({
        next: async result => {
            this.userInformation.next(await response.json());
        },
    });
}

Answer №2

No one seems to be making a call to getCurrentUser(), which means that no actual HTTP request is being triggered:

@Component({
    selector: 'app-topbar',
    templateUrl: './topbar.component.html',
    styleUrls: ['./topbar.component.scss'],
})
export class TopbarComponent implements OnInit {
    public user: User | null = new User();

    constructor(
        private authService: AuthService,
        private router: Router,
        public userService: UserService,
    ) {
        this.userService.userOnChange.subscribe({
            next: value => {
                if (value != null) {
                    this.user = value as User;
                    console.log(value.Username);
                    console.log(this.user.Username);
                }
            },
        });
        this.userService.getCurrentUser(); <-- consider adding this line
    }

    ngOnInit(): void {

    }
}

In addition, your current setup requires dealing with subscriptions even after the component has been destroyed. You can simplify it like this:

export class TopbarComponent implements OnInit {
    public user$: BehaviorSubject<User | null>;

    constructor(
        private authService: AuthService,
        private router: Router,
        private userService: UserService,
    ) {
        this.user$ = this.userService.userOnChange;
        this.userService.getCurrentUser();
                
    }

    ngOnInit(): void {

    }
}

and use this template:

<span *ngIf="user$ as user"> user: {{ user.Username }}</span>

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

What could be causing the TypeScript class property to be undefined?

Below is the code snippet I am working with: class FeedbackController { public homePage(req, res){ this.test(); res.send('Welcome to feedback service'); } private test(){ console.log('test called'); } } export de ...

Looking to update the display of an array received in JSON format and then show it using ng-repeat?

Upon receiving a response from the backend, I am saving it in a variable called "allinfo" in my controller. The data received includes the name, date of birth, and hobby of a person. The hobby is an array that can contain any number of elements. In my vie ...

AngularMap with mapping as the value

Can I implement a Map<string, Map<string, number>> collection in my Angular project? I attempted to create and initialize the variable, but encountered an error when trying to set values. Here is an example: //define variable public players: M ...

Performing an Angular 5 JSONP request using custom HttpHeaders

I'm attempting to make a JSONP request with specific HTTP header parameters. Using http.get makes it simple: let header = new HttpHeaders(); header.append(<header_param_name>, <header_param_value>); this.http.get(<my_url>, { header ...

If the input is unmounted in react-hook-form, the values from the first form may disappear

My form is divided into two parts: the first part collects firstName, lastName, and profilePhoto, while the second part collects email, password, confirmPassword, etc. However, when the user fills out the first part of the form and clicks "next", the val ...

Why is my input field value not getting set by Angular's patchValue function

I've been attempting to populate an input field using the form group with patchValue(), but for some reason, the input remains empty. Here's a snippet of my code... component.html <form [formGroup]="createStoreForm" (ngSubmit)="createStor ...

Unable to alter the vertex color in three.js PointCloud

I'm currently facing an issue with changing the color of a vertex on a mouse click using three.js and Angular. After doing some research, I believe that setting up vertex colors is the way to go. My approach involves setting up vertex colors and then ...

Issues arise when attempting to use the Android KeyUp, KeyDown, and KeyPress events in conjunction with Angular2

I am encountering an issue where I consistently receive a keyCode of 229 in Android Chrome browsers when running either: <input type="text" (keydown)="testKeyCodes($event)"/> <!-- or --> <input type="text" (keyup)="testKeyCodes($event)"/& ...

Creating multiple ui-grids dynamically using Angular can enhance the user experience and increase the flexibility

We are facing a scenario where there are 2 fixed Bootstrap tabs and any number of dynamic tabs. These dynamic tabs are required to contain two ui-grids each. Currently, we are focusing on getting just one ui-grid to function. We have an array of a custo ...

Are there any tools available to eliminate the need for inline annotation injection in the Rails Asset Pipeline when using AngularJS?

I am currently working on a Rails + AngularJS project without using inline annotation injection and relying on gulp-ngcompile to compile my scripts. However, I'm considering switching from gulp to the asset pipeline. Can anyone recommend any asset pip ...

React with TypeScript: The struggle of getting LocalStorage to work

Currently, I am dealing with persistence in a todo application developed using React and TypeScript. To achieve the desired persistence, I have implemented localStorage. Allow me to share some code snippets: const [todos, setTodos] = useState<todoMod ...

Creating a Circle with Pixi.js v4 and Typerscript in IONIC 2

I have been attempting to create a custom class in TypeScript that utilizes PIXI.js to draw circles. Below is the code for my home.ts class: import { Component, ViewChild, ElementRef } from '@angular/core'; import { NavController } from 'i ...

Which option is more beneficial for intercepting API data in Angular 6: interfaces or classes?

My API returns JSON data that is not structured the way I need it, so I have to make changes. { "@odata.context":"xxxxxx", "id":"xxxxxxxx", "businessPhones":[ ], "displayName":"name", "givenName":"pseudo", "jobTitle":null, "ma ...

Collective feedback received from several HTTP requests initiated in a sequential loop

I am seeking advice on an efficient method to perform multiple HTTP requests asynchronously, and then merge all of the responses into a single array. Here is an example snippet of the code I am working with: getSamples(genes) { genes.forEach(gene ...

Troubleshooting the challenge of transitioning from Angular 4 to Angular 9 with flatMap

In my Angular 4 code, everything runs smoothly: public resolve(): Observable<GridViewDtcConfig> { const permissionResponse = this.flowsService.getPermissions(); return permissionResponse.flatMap((permissions) => { c ...

What causes the placeholder to be invisible in a select/option when ngModel is used?

While using a select with ngModel to capture the value of the options, I noticed that when I render it, there is no placeholder displayed as shown in the image below: This is the code snippet: <select [value]="selected_tipo" [(ngModel)]=&q ...

Ways to deactivate Kendo UI draggable function

While working in my Angular-Kendo setup, I have implemented a Drag/Drop functionality on the rows of two grids. I referred to this example as the basis for my code : http://jsfiddle.net/BtkCf/4/ The row drag feature is functioning properly, but it seems ...

Angular 5 Image Upload - Transfer your images with ease

I am having trouble saving a simple post in firebase, especially with the image included. This is my current service implementation: uploadAndSave(item: any) { let post = { $key: item.key, title: item.title, description: item.description, url: '&a ...

What is the best way to retrieve the rendered content through the `link` function of a directive?

Here is the code snippet below: <div class="test">{{name}}</div> This Angular code demonstrates how to alert the rendered string World: var app = angular.module('angularjs-starter', []); app.controller('MainCtrl', functi ...

"Issue with default select value in Angular using ngModel - one select element not setting default value, while another works fine

Why is this functioning properly? File: myComponent1.html <select id="BisMonat" class="form-control" [(ngModel)]="currentmonatbis"> <option [value]="01">Januar</option> <option [value]="02">Feb ...