仅在单击按钮两次

时间:2018-02-14 10:43:58

标签: angular typescript

我已经完成了一个月的尝试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)在第一次单击时显示未定义,但在第二次单击时会在控制台上显示正确的值。我做错了什么?

1 个答案:

答案 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。

如果这不够了,请随意提问!