0

I'm trying to refresh my UI based on a retrieved list from a service. Like this:

HTML part:

<li *ngFor="let test of testsList" class="list-inline-item">
       <div class="row m-row--no-padding align-items-center">
             <div class="col">
               <button
               [disabled]="test.locked"
               [ngClass]="{locked: test.locked, disabled: test.status == 1}"
               (click)="selectTest(test)"
               class="square"></button>
             </div>
        </div>
    </li>

Where my testsList comes from a promise on the API and it's retreived in ngOninit:

this._myService.getAllTests().then((tests: TestDto[]) => {
        this.testsList = tests;
}

From a child component, I want to come back to this component (the root one) and paint the updated list of tests. To navigate back to the parent component, I use the router.navigate(...):

this._router.navigate(['app/tests/all']);

The background data is being updated, as I can check in database and when I refresh manually the page. But when I navigate to it, the UI doesn't show the changes...

I tried several things like this, this and tried also this one but I think I didn't implement it in the correct way...

As additional info, I attach the pages structure:

/tests (root page)
   |
(child pages)
   |----> all
   |---->description
   |---->....
   |---->summary

And I jump from /all to /summary, I update some data in /summary that must be rendered when jumping back to /all page.

How can I refresh the UI or bind to the value so it updates whenever the 'app/tests/all' page is called?

EDIT:

getAllTests() {
    return new Promise((resolve, reject) => {
        this._testsService.getAllTests().subscribe( (result) => {
            this.tests = this.orderAsc(result.items);
            resolve(this.tests);
        }, error => {
            console.log('No tests loaded from Database');
            reject();
        });
    });
}
Sonhja
  • 8,230
  • 20
  • 73
  • 131

2 Answers2

1

OK, your problem is that you are wrapping a observable with a Promise, and Promises handles only 1 async operation, instead the Observable is like a stream of events. You can see very good explanations of the difference between them here: What is the difference between Promises and Observables?

So, for your case, you could return directly an observable like this:

getAllTests() {
  return this._testsService.getAllTests().pipe(
    map((result) => {
      this.tests = this.orderAsc(result);
      return (this.tests);
    }),
    catchError(err => ('No tests loaded from Database'))
  );
}

With the map you transform the result that comes from your database and getAllTests() is now returning an observable that you can subscribe to in your component like this:

this._myService.getAllTests().subscribe((tests: TestDto[]) => {
  this.testsList = tests;
});

Or even better, instead of subscribing in the component, you could use the async pipe in the html:

<li *ngFor="let test of testsList$ | async" class="list-inline-item">

And in your component you have to declare a variable of type Observable:

  public testsList$: Observable<TestDto[]>;

And assign it to the function _testsService.getAllTests() like this:

this.testsList$ = this._myService.getAllTests();
0

Maybe it's not the most appropiate way but I added this to the constructor of the Component I need to be refreshed:

this._router.routeReuseStrategy.shouldReuseRoute = function () {
            return false;
          };

And it worked...

Sonhja
  • 8,230
  • 20
  • 73
  • 131