I am new to angular and started leaning angular 4. Data not binding with ngfor
directive on a component using the async pipe. Please help
user service uses HTTP request to get data from API:
user.service.ts
import { Injectable } from '@angular/core';
import { Http, Response, Headers, RequestOptions } from '@angular/http';
import { Observable } from 'rxjs/Observable';
import 'rxjs/add/operator/map';
import 'rxjs/add/operator/do';
import 'rxjs/add/operator/catch';
import { User } from "../Models/user";
@Injectable()
export class UserService {
constructor(private http: Http) { }
get(url: string): Observable<User[]> {
return this.http.get(url)
.map(response => response.json() as User[])
// .do(data => console.log("All: " + JSON.stringify(data)))
.catch(this.handleError);
}
private handleError(error: Response) {
console.error(error);
return Observable.throw(error.json().error || 'Server error');
}
}
Here i am using observable User[] interface for user list:
user.component.ts
import { Component, OnInit, ViewChild } from '@angular/core';
import { UserService } from '../Services/user.service';
import { FormBuilder, FormGroup, Validators } from '@angular/forms';
import { ModalComponent } from 'ng2-bs3-modal/ng2-bs3-modal';
import { User } from '../Models/user';
import { DBOperation } from '../Shared/enum';
import { Observable } from 'rxjs/Observable';
import { Global } from '../Shared/global';
@Component({
templateUrl: 'app/Components/user.component.html'
})
export class UserComponent implements OnInit {
@ViewChild('modal') modal: ModalComponent;
users$: Observable<User[]>;
user: User;
msg: string;
indLoading: boolean = false;
userForm: FormGroup;
dbops: DBOperation;
modalTitle: string;
modalBtnTitle: string
constructor(private fb: FormBuilder, private userService: UserService)
{ }
ngOnInit(): void {
this.userForm = this.fb.group({
Id: [''],
UserName: ['', Validators.required],
Password: ['', Validators.required],
FirstName: ['', Validators.required],
LastName: ['', Validators.required],
Gender: ['', Validators.required]
});
this.LoadUsers();
}
LoadUsers(): void {
this.indLoading = true;
this.users$ = this.userService.get('http://localhost:29712/api/userapi/');
this.indLoading = false;
}
}
Template for the async pipe to subscribe observable users variable:
user.component.html
<div class='panel panel-primary'>
<div class='panel-heading'>
User Management
</div>
<div class='panel-body'>
<div class='table-responsive'>
<div class="alert alert-info" role="alert" *ngIf="indLoading"><img src="../../images/loading.gif" width="32" height="32" /> Loading...</div>
<div *ngIf='users && users.length==0' class="alert alert-info" role="alert">No record found!</div>
<table class='table table-striped' *ngIf='users && users.length'>
<thead>
<tr>
<th>First Name</th>
<th>Last Name</th>
<th>Gender</th>
</tr>
</thead>
<tbody>
<tr *ngFor="let user of users$ | async">
<td>{{user.FirstName}}</td>
<td>{{user.LastName}}</td>
<td>{{user.Gender}}</td>
</tr>
</tbody>
</table>
<div>
</div>
</div>
<div *ngIf="msg" role="alert" class="alert alert-info alert-dismissible">
<button type="button" class="close" data-dismiss="alert" aria-label="Close"><span aria-hidden="true">×</span></button>
<span class="glyphicon glyphicon-exclamation-sign" aria-hidden="true"></span>
<span class="sr-only">Error:</span>
{{msg}}
</div>
</div>
/api/userapi/
request will be executed twice – yurzuiresponse => response.json() as IUser[]
resolves to null. are you sure that service responds with the same data structure as your IUser is? – dee zgngIf="users && users.length"
whereusers
is Observable – yurzui