Angular UI failing to refresh despite Observable subscription activation

I'm facing an issue with my Angular page where the UI is not updating when the observable parameter from a service changes.

I've experimented with storing the observable result in a flat value and toggling a boolean to update the UI, but none of these approaches have worked.

Upon logging the observable, I can verify that it is updating correctly. Interestingly, navigating back to the page displays the updated value.

All other conditional UI updates work as expected, except for the one below (

*ngIf="(entries$ | async), else loading"
) which seems to be causing the problem.

component.ts

export class EncyclopediaHomeComponent implements OnInit {
  entries$: Observable<EncyclopediaEntry[]>;
  categories$: Observable<string[]>;
  entry$: Observable<EncyclopediaEntry>;
  entry: EncyclopediaEntry;
  isEditing: boolean;

  constructor(private route: ActivatedRoute, private encyService: EncyclopediaService) {
    this.entries$ = encyService.entries$;
    this.categories$ = encyService.categories$;

    this.entries$.subscribe(es => {
      console.log(es);
    });

    route.url.subscribe(url => this.isEditing = url.some(x => x.path == 'edit'));
    this.entry$ = route.params.pipe(
      switchMap(pars => pars.id ? encyService.getEntry(pars.id) : of(null)),
    );
    this.entry$.subscribe(entry => this.entry = entry);
  }

  ngOnInit(): void {
  }

  updateEntry(entry: EncyclopediaEntry) {
    this.encyService.updateEntry(entry.id, entry);
  }
}

component.html

<div class="encyclopedia-container">
    <ng-container *ngIf="(entries$ | async), else loading">
        <app-enc-list [entries]="entries$ | async"
            [selectedId]="entry ? entry.id : null"></app-enc-list>

        <ng-container *ngIf="entry">
            <app-enc-info *ngIf="!isEditing, else editTemplate"
                [entry]="entry$ | async"></app-enc-info>

            <ng-template #editTemplate>
                <app-enc-edit [entry]="entry$ | async" [categories]="categories$ | async"
                    (save)="updateEntry($event)"></app-enc-edit>
            </ng-template>
        </ng-container>
    </ng-container>
    <ng-template #loading>
        <mat-progress-bar mode="indeterminate"></mat-progress-bar>
        <br>
        <p>Loading Encyclopedia...</p>
    </ng-template>
</div>

edit: service.ts

export class EncyclopediaService {
  entriesSubject = new ReplaySubject<EncyclopediaEntry[]>();
  entries$ = this.entriesSubject.asObservable();
  private _entries: EncyclopediaEntry[];

  constructor(private file: FileService) {
    file.readFromFile(this.projectName+'Encyclopedia').subscribe((es: string) => {
      this._entries = JSON.parse(es);
      this.entriesSubject.next(this._entries);
      this.entries$.subscribe(es => this.file.writeToFile(this.projectName+'Encyclopedia', JSON.stringify(es)));
    });
  }
  .
  .
  .
}

Answer №1

It appears that the component is not detecting changes as expected. I am unsure why this is happening, as |async should handle this.

To resolve this issue, you can utilize the ChangeDetector:


constructor(
   private route: ActivatedRoute,  
   private encyService: EncyclopediaService
   private changeDetectorRef: ChangeDetectorRef,
) {
    this.entries$ = encyService.entries$;
    this.categories$ = encyService.categories$;

    this.entries$.subscribe(es => {
      // setTimeout is necessary to ensure smooth operation with ng changes detector
      setTimeout(_=>{this.changeDetectorRef.detectChanges()},0);
      ...
    });

Alternatively, you can use markforCheck as outlined here.

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

Check the type of the indexed value

I need help with a standard interface: interface IProps<T> { item: T; key: keyof T; } Is there a way to guarantee that item[key] is either a string or number so it can be used as an index for Record<string | number, string>? My codeba ...

Is it necessary to only override the monospaced font?

Can the monospace font in Angular Material be customized for just the <code>foo</code> blocks? I want to use a font where the number zero 0 looks distinct from the letter oh O. ...

Utilizing a function in an infinite loop within *ngFor along with an asynchronous pipe for an HTTP call

Using a function in an *ngFor statement: @Component({ selector: 'foo-view', template: '<div *ngFor="let foo of loadAll() | async"></div>' }) export class FooComponent { loadAll(): Observable<Foo[]> { return ...

Hiding the initial parent SVG element in the list will also hide all subsequent SVG elements within each section, excluding the container

I encountered a strange issue with my code in the Next framework. When using getServerSideProps, I made a request to my api folder, which resulted in a simple JSON response. Everything seemed to be working fine. The content was displayed perfectly without ...

Encountering a hiccup during the installation process of Angular CLI

I'm encountering an issue in the command line, seeking assistance C:\Users\admin>npm -v 6.9.0 C:\Users\admin>npm install -g @angular/cli npm ERR! Unexpected end of JSON input while parsing near '...vkit/core":"8.0.4", ...

Enhance the Nuxt 3 experience by expanding the functionality of the NuxtApp type with

When I include a plugin in my NuxtApp, it correctly identifies its type. https://i.stack.imgur.com/UFqZW.png However, when I attempt to use the plugin on a page, it only displays the type as "any." https://i.stack.imgur.com/hVSzA.png Is there a way for ...

Exploring 2D arrays in AngularJS - A comprehensive guide

I have the following array declared in my JavaScript file var myApp = angular.module('myApp',[]); function MyCtrl($scope) { $scope.name = 'Superhero'; $scope.tempArr = [ ["block A1", "block B1", "block C1"], ["block ...

Trigger a function in JavaScript by clicking on an element and passing its class

I have written the following code: <?php $extCount = 0; foreach($this->externalReferal as $externalReferal) { $extCount++; ?> <div class='fieldtestPct' > <div class='fieldItemLabel'> < ...

To demonstrate movement through both revealing and concealing

Currently, I am working on an assignment that involves rotating an image on hover. My task is to rotate the image first, then animate another object once the image rotation is complete. Upon mouse out, the initial image should return to its original positi ...

How to rename a class of an image tag using jQuery

I need to update the class name in my image tag <img src="img/nex2.jpeg" class="name"> When hovering over with jquery, I want to add a new class to it. After hovering, the tag should appear as follows: <img src="img/nex2.jpeg" class="name seco ...

The error message "Theme does not include property 'navHeight'" is indicating that the 'navHeight' property is not defined within the 'Theme' type. This issue occurs when using MUI v5 syntax with Types

When attempting to incorporate MUI with new props declared in the Interface inside the theme.ts file (as suggested by the MUI docs), I encountered the error mentioned above while theme.palette.primary.main does work. Despite trying various solutions like i ...

Unexpected "<" and dual output in jade include seem to defy explanation

i am currently redesigning my website to incorporate dynamic includes. These includes are pre-rendered on the server and then passed to res.render() however, I am encountering unexpected occurrences of < and > on the page, along with the issue of th ...

How can I save a TypeScript object to Firebase using serialization?

Having an issue: Within my angular application, I have implemented a lot of classes with inheritance. However, upon attempting to save these objects to Firebase, I encountered an error indicating that I am trying to persist custom objects which is not supp ...

I'm perplexed by setting up Node.js in order to work with Angular.js

Currently following the Angular tutorial provided at https://docs.angularjs.org/tutorial, but I'm encountering confusion with the Node.js installation. Having already installed node globally on my Mac, the tutorial mentions: The tutorial instructio ...

What sets apart 'hasClass' from 'is'? Additionally, is there a substitute to retrieve a Jquery element instead?

Similar Question: jQuery .hasClass() vs .is() Sample HTML code: <div class="results"> <div class="table"> <form class="tr" action="#" method="post"> <div class="td"> <input class="dat ...

Tips for automatically scrolling images horizontally in responsive layouts

Recently, I've been working on a website called . On the homepage, my portfolio images are arranged in a grid format using the <li> tag. I'm looking to align them side by side and have them scroll horizontally automatically, preferably with ...

Button react-native press following textInput within scroll view aware of keyboard movements

I'm currently facing an issue where I have a TextInput and a button nested inside a KeyboardAwareScrollView. The goal is for the user to input some text and then tap the button created using TouchableOpacity, which should send the inputted text forwar ...

Is it necessary to separate Lodash orderby functions to ensure they function correctly?

For some reason, I'm having trouble sorting my data using lodash in my front-end client code. All the examples I've come across don't involve working with data in an interface, so I can't figure out where I'm going wrong. Let&apo ...

Ordering and displaying data with AngularJS

Trying to maintain a constant gap of 5 between pagination elements, regardless of the total length. For instance, with $scope.itemsPerPage = 5 and total object length of 20, we should have 4 pages in pagination. However, if $scope.itemsPerPage = 2 and tota ...

What is the reason that certain functionalities do not work on an element that has two CSS classes assigned to it

I have a unique situation with two input elements and a button: <input class="close-acc-usr opt-in" type="text" name="closeAccUsr" /> <input class="close-acc-pin opt-in" type="number" name="cl ...