Kazi
Kazi

Reputation: 1553

*ngIf condition is not updated after an HTTP request is finished?

I have a button which when clicked by users calls the GitLab API and renders fetched data. Unfortunately I need to click the button twice to show the data. At the very first click it does not display anything.

Here is the HTML template code:

<div *ngIf="!afterLogIn">
  <button (click)="apiData()">Gitlab project</button>
</div>

<div class="content" *ngIf="afterLogIn" >

  <div *ngFor="let data of api">
    <div class="item">
      <div class="flag"></div>
      <div class="description">
        <div class="title styles-pro-medium-bold">
          {{ data.name }}
        </div>
        <div class="about styles-pro-small">
          {{ data.description}}
        </div>
      </div>
      <div class="more styles-pro-header">
        <div class="more">
          ...
        </div>
      </div>
    </div>
  </div>
</div>

my component.ts file:

constructor(
    private router: Router,
    private store$: Store<RootStoreState.State>,
    private gitLabApi: GitLabApiService
  ) {}   
apiData() {
        this.gitLabApi.getApi().subscribe(apiData => {
          this.api = apiData;
          console.log(this.api);  // first click showed the data in console

        this.afterLogIn = true;
        });
       }

Here is the service I am using:

export class GitLabApiService {
    url ='https://gitlab.com/api/v4/projects?access_token=sometoken&owned=true&simple=true';
      constructor(private http: HttpClient) {}

      getApi(): Observable<any> {
        return this.http.get<any>(this.url);
      }
}

How can I solve this problem?

Upvotes: 0

Views: 433

Answers (1)

Poul Kruijt
Poul Kruijt

Reputation: 71911

Problem is that change detection is not being triggered. If you want to keep using OnPush you need to adjust your code a bit:

constructor(
  private router: Router,
  private store$: Store<RootStoreState.State>,
  private gitLabApi: GitLabApiService,
  private cd: ChangeDetectorRef  // add this line
) {} 

apiData() {
  this.gitLabApi.getApi().subscribe(apiData => {
     this.api = apiData;
     this.afterLogIn = true;
     this.cd.markForCheck() // add this line
  });
}

Or, you can even use the async pipe like this:

<div class="content" *ngIf="afterLogIn">
  <div *ngFor="let data of api | async">
  //...

and change your code to:

apiData() {
  this.api = this.gitLabApi.getApi().pipe(
    tap(() => this.afterLogIn = true)
  );
}

Upvotes: 2

Related Questions