简体   繁体   中英

angular5:ngFor works only in second button click

My scenario as follows

1) When the user enters a keyword in a text field and clicks on the search icon it will initiate an HTTP request to get the data.

2)Data is rendered in HTML with ngFor

The problem is on the first click the data is not rendered in HTML but I am getting the HTTP response properly, and the data rendered only on second click.

component.ts

export class CommerceComponent implements OnInit {


  private dealList = [];

  //trigger on search icon click
  startSearch(){

     //http service call
     this.getDeals();
  }

  getDeals(){

     this.gatewayService.searchDeals(this.searchParams).subscribe(
      (data:any)=>{
        this.dealList = data.result;
        console.log("Deal list",this.dealList);
      },
      (error)=>{
         console.log("Error getting deal list",error);
         this.dealList = [];
         alert('No deals found');
      }
    );
  }

}

Service.ts

searchDeals(data){

   var fd = new FormData();
   fd.append('token',this.cookieService.get('token'));
   fd.append('search',data.keyword);

   return this.http.post(config.url+'hyperledger/queryByParams',fd);

}

HTML

//this list render only on second click
<div class="deal1"  *ngFor="let deal of dealList">
     {{deal}}
 </div>

UPDATE

click bind html code

 <div class="search-input">
          <input type="text" [(ngModel)]="searchParams.keyword" class="search" placeholder="" autofocus>
          <div class="search-icon" (click)="startSearch()">
            <img src="assets/images/search.png">
          </div>
        </div>

According to Angular official tutorial , you could have problems if you bind a private property to a template:

Angular only binds to public component properties.

Probably, setting the property dealList to public will solve the problem.

Try this:

this.dealList = Object.assign({},data.result);

Better do this inside the service.

By default, the angular engine renders the view only when it recognizes a change in data.

Remove "private" from your dealList variable. That declaration makes your component variable available only during compile time.

Another problem: you are implementing OnInit in yout component but you are not using ngOnInit. Angular is suposed to throw an error in this situation.

My suggestion is to switch to observable:

I marked my changes with CHANGE

component.ts

// CHANGE
import { Observable } from 'rxjs/Observable';
// MISSING IMPORT
import { of } from 'rxjs/observable/of';

export class CommerceComponent implements OnInit {
    // CHANGE
    private dealList: Observable<any[]>; // you should replace any with your object type, eg. string, User or whatever

    //trigger on search icon click
    startSearch() {
       //http service call
        this.getDeals();
    }

    getDeals() {
        this.gatewayService.searchDeals(this.searchParams).subscribe(
            (data:any)=>{
                // CHANGE
                this.dealList = of(data.result);
                console.log("Deal list",this.dealList);
            },
            (error)=>{
                console.log("Error getting deal list",error);
                // CHANGE
                this.dealList = of([]);
                alert('No deals found');
            }
        );
    }
}

HTML

<!-- CHANGE -->
<div class="deal1"  *ngFor="let (deal | async) of dealList">
    {{deal}}
</div>

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM