1

In my angular2 application I am retrieving data from Firebase database using query and storing it in a FirebaseListObservable. In my getStatus method I want to find out the number of elements in that FirebaseListObservable. If the list has any elements I want to return 'glyphicon-ok', and if the list is empty I want to return 'glyphicon-remove'. I have shared my code below which is not working.

component.ts

assignments: FirebaseListObservable<any>
submission: FirebaseListObservable<any>

ngOnInit() {
this.assignments = this._getAsnService.getAsnByCourseBatch(AuthService.courseBatch);
}

getStatus(asnDetailKey) {
  //  Searching assignment in database
  this.submission = this._db.list(`/submissions/${AuthService.uid}/`, {
    query: {
      orderByChild: 'asnDetailKey',
      equalTo: asnDetailKey
    }
  });

  //  If assignment is found return 'glyphicon-ok' else return 'glyphicon-remove'
  this.submission.subscribe(sub => {
    this.status = sub.length > 0 ? 'glyphicon-ok' : 'glyphicon-remove';
  });

  return this.status;
} 

component.html

<table class="table table-bordered" *ngIf="!isLoading">
    <tr>
      <th>Name</th>
      <th>Subject</th>
      <th>Due Date</th>
      <th>Status</th>
    </tr>
    <tr *ngFor="let assignment of assignments | async" [hidden]="filter(assignment)">
      <td> <span class="AsnName" [routerLink]="['view', assignment.$key]"> {{ assignment.AsnName }} </span> </td>
      <td> {{ assignment.subject }} </td>
      <td> {{ assignment.dueDate }} </td>
      <td> <i class="glyphicon" [ngClass]="getStatus(assignment.$key)"></i> </td>  // <==== calling getStatus(assignment.$key)
    </tr>
</table>

Thanks.

PR7
  • 1,524
  • 1
  • 13
  • 24

1 Answers1

0

Update: I misunderstood what you were going for the first time. It sounds like you want to make an initial call to get the assignments, then render those in an ngFor. At that point you want to make an additional call for each item to determine what kind of icon should appear in that ngFor iteration.

This is what I came up with (https://plnkr.co/edit/UqHDzZMlkNQ0mXfuoIO2?p=info). Essentially each ngFor iteration is calling the getClass() method with an async pipe. At that point an observable is created and stored in the component. This isn't super elegant because the getClass() method is fired multiple times while ngClass waits for a response. (you can see this in the console)

There may be a better way to do this. Perhaps with async/await functions (https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Statements/async_function)

As a possible alternative, I would prefetch all the data you need before rendering with ngFor. This way you'll totally avoid asynchronous responses + ngClass.


You could subscribe to the observable in your component (instead of using the async pipe) and determine the color after the assignments are returned.

// component.ts
getStatus(asnDetailKey){
    this.submission = this._db.list(`/submissions/${AuthService.uid}/`, {
        query: {
            orderByChild: 'asnDetailKey',
            equalTo: asnDetailKey
        }
    }).subscribe(
        res => {
            this.assignments = res;
            this.color = res.length !== 0 ? 'green' : 'red';
        },
        err => {}
    )
}

// component.html
<i class="glyphicon glyphicon-ok" [style.color]="color"></i>

LLai
  • 13,128
  • 3
  • 41
  • 45
  • did you mean `this.color = res.length != 0 ? 'green' : 'red';` ? – PR7 Jun 26 '17 at 14:30
  • seems like [class.color] is not working. I tried it with hardcoded value and it is not working idk why. ` ` is not showing red color on icon. – PR7 Jun 26 '17 at 14:38
  • @PR7 I would use !== instead of != because it matches type https://stackoverflow.com/a/359509/7176268. I believe you want [style.color] – LLai Jun 26 '17 at 14:50
  • isnt it possible to do it inside the getStatus method instead of ngOnInit. I am trying to do it this way but it isnt working yet `getStatus(asnDetailKey) { this.submission = this._db.list(`/submissions/${AuthService.uid}/`, { query: { orderByChild: 'asnDetailKey', equalTo: asnDetailKey } }); this.submission.subscribe( sub => { this.status = sub.length > 0 ? 'glyphicon-ok' : 'glyphicon-delete'; }); }` and html ` ` Returning glyphicon instead color. – PR7 Jun 26 '17 at 17:12
  • @PR7 you are correct, you can subscribe to the observable anywhere you want in the component. I'll update my answer accordingly – LLai Jun 26 '17 at 17:13
  • @PR7 your subscription looks good. Now that you have stored your class into the status variable, your html just needs to use that value [ngClass]="status" – LLai Jun 26 '17 at 17:19
  • Let us [continue this discussion in chat](http://chat.stackoverflow.com/rooms/147644/discussion-between-llai-and-pr7). – LLai Jun 26 '17 at 17:20