我已经完成了一个月的尝试Angular的手。我对Web开发很陌生,冒着听起来像新手的风险,我发布了这个问题。
我创建了一个简单的角度应用程序,只需单击一个名为roomSearch()
的按钮,就可以将一些表单数据发送到MVC Web API。结果数据从Web API发送回角度组件,该组件在html页面中显示它。
问题是如果我必须看到结果,我总是需要点击两次按钮。它不会单击一下,我很难搞清楚原因。
这是我的代码:
我的HTML:
<form #roomForm="ngForm" class="coupon-form" (ngSubmit)="onSubmit(roomForm)">
<div class="row">
<div class="col-xs-6 form-group">
<label>Start Date</label>
<input type="date" class="form-control" name="startDate" #startDate="ngModel" [(ngModel)]="roomService.userSelection.startDate" placeholder="Start Date" required>
</div>
<div class="col-xs-6 form-group">
<label>End Date</label>
<input type="date" class="form-control" name="endDate" #endDate="ngModel" [(ngModel)]="roomService.userSelection.endDate" placeholder="End Date" required>
</div>
</div>
<div class="form-group">
<button type="button" (click)="roomSearch(roomForm)" class="btn btn-lg btn-block btn-info"><i class="fa fa-floppy-o" aria-hidden="true"></i> Submit</button>
</div>
</form>
<br/>
<table *ngIf="show" class="table table-sm table-hover">
<p><b>Rooms We Could Find For You</b></p>
<tr>
<td>{{roomService.finalRoom1/(roomService.roomList.length)}}</td>
<td>{{roomService.finalRoom2/(roomService.roomList.length)}}</td>
<td>{{roomService.finalRoom3/(roomService.roomList.length)}}</td>
<td>{{roomService.finalRoom4/(roomService.roomList.length)}}</td>
</tr>
</table>
组件文件:
show: boolean;
ngOnInit() {
this.show = this.roomService.show;
}
roomSearch(form: NgForm)
{
this.show = this.roomService.getRoomList(form.value.startDate, form.value.endDate);
}
Service FIle
constructor(private http: Http) {
this.show=false;
}
getRoomList(startDate: string, endDate:string){
this.finalUrl = this.apiRoot + '?startDate='+ startDate + '&endDate='+ endDate;
this.show=true;
this.http.get(this.finalUrl)
.map((data: Response)=>{
return data.json() as Room[];
}).toPromise().then(x =>{
this.roomList = x;
});
console.log(this.roomList);
if(this.roomList!=null){
this.finalRoom1 = 0; this.finalRoom2 = 0; this.finalRoom3 = 0; this.finalRoom4 = 0;
this.priceRoom1 = 0; this.priceRoom2 = 0; this.priceRoom3 = 0; this.priceRoom4 = 0;
this.roomList.forEach((e:any) => {
this.finalRoom1 = this.finalRoom1 + Number(e.UnitPrice1);
this.finalRoom2 = this.finalRoom2 + Number(e.UnitPrice2);
this.finalRoom3 = this.finalRoom3 + Number(e.UnitPrice3);
this.finalRoom4 = this.finalRoom4 + Number(e.UnitPrice4);
});
console.log(this.roomList); //This statement shows undefined at first click but on the second click showcases the correct value on the console.
if(this.finalRoom1>0)
this.show=true;
else
this.show=false;
return this.show;
}
上面的代码行console.log(this.roomList)
在第一次单击时显示未定义,但在第二次单击时会在控制台上显示正确的值。我做错了什么?
答案 0 :(得分:2)
首先,感谢你的代码格式化。很高兴看到它!
其次,您面临的是异步问题。
当你进行HTTP调用时,Angular使用 Observables (在你的情况下,你将它转换为 Promises ,但原理是相同的)。 Observables / Promises是异步的,意味着结果将在稍后出现,而不是在您提出请求时。
在您的情况下会发生什么:
this.http.get(this.finalUrl)
.map((data: Response)=>{
return data.json() as Room[];
}).toPromise().then(x =>{
this.roomList = x;
});
console.log(this.roomList);
您不等待承诺已解决(a.k.a。有结果)。这就是您有undefined
日志的原因。
你应该试试这个:
processRequest(roomList: Room[]) {
if (roomList != null) {
this.finalRoom1 = 0; this.finalRoom2 = 0; this.finalRoom3 = 0; this.finalRoom4 = 0;
this.priceRoom1 = 0; this.priceRoom2 = 0; this.priceRoom3 = 0; this.priceRoom4 = 0;
roomList.forEach((e: any) => {
this.finalRoom1 = this.finalRoom1 + Number(e.UnitPrice1);
this.finalRoom2 = this.finalRoom2 + Number(e.UnitPrice2);
this.finalRoom3 = this.finalRoom3 + Number(e.UnitPrice3);
this.finalRoom4 = this.finalRoom4 + Number(e.UnitPrice4);
});
console.log(roomList); //This statement shows undefined at first click but on the second click showcases the correct value on the console.
if (this.finalRoom1 > 0)
this.show = true;
else
this.show = false;
return this.show;
}
}
在您的代码中,删除之后的所有内容:
return this.http.get(this.finalUrl)
.map((data: Response) => {
return data.json() as Room[];
}).toPromise().then(x => {
return Promise.resolve(this.processRequest(x))
});
最后,在您的组件中,您必须这样做:
roomSearch(form: NgForm)
{
this.roomService.getRoomList(form.value.startDate, form.value.endDate).then(show => this.show = show);
}
用文字向你解释:
发出HTTP请求以获取房间,然后订阅,然后等待结果。结果出现后,使用processRequest处理请求并返回此过程的结果。处理完成后,由于我订阅了结果,将结果绑定到我的组件的变量show。
如果这不够了,请随意提问!