child with input binding angular 5 calling multiple times

375 Views Asked by At

I'm making a website in angular 5. I'm using input binding in one of the components.

<app-recommend-popular [comp]="component" [recommended]="recommendedHotels" [popular]="popularHotels"></app-recommend-popular>

For 'recommendedHotels' I'm getting data from HTTP Service. From mongo DB I'm only fetching three records. It is a JSON object. And It should appear like in figure1

'app-recommend-popular' Component is used in a Component Hotels. and it calls the service function in the constructor of Hotel(to get data).
The first time the component is called, all went okay. but when I come back to the same component it's double the things. like inFigure2

@Component({
 selector: 'app-recommend-popular',
  templateUrl: './recommend-popular.component.html',
  styleUrls: ['./recommend-popular.component.css']
})
export class RecommendPopularComponent implements OnInit{
  @Input() comp: string;
  @Input() recommended: string;
  @Input() popular: string;
  public recommendedThings: string[];
  constructor() {
  }
  getRepeater(ratingTotal) {
    return new Array(ratingTotal);
  }

  ngOnInit() {
  }
}

HTML CODE is here:

  <div class="card-deck">
    <div class="card" *ngFor="let r of recommended">
      <img class="card-img-top" src="{{ r.Image }}" alt="Card image cap">
      <div class="cardbody">
        <div class="row">
          <div class="col-sm-6 col-xs-6">
            <h5 class="card-title">{{ r.Name }}</h5>
          </div>
          <div class="col-sm-6 col-xs-6 alignRight">
            <p style="float: right">PKR {{ r.Price }}</p>
          </div>
        </div>
        <div class="row">
          <div class="col-sm-6 col-xs-6">
            <div>
              <span *ngFor="let str of getRepeater(r.Rating)" class="fa fa-star" aria-hidden="true"></span>
            </div>
            <div>
              {{ r.Rating }}/5 (120 reviews)
            </div>
          </div>
          <div class="col-sm-6 col-xs-6 alignRight">
            <a class="btn btn-success" routerLink="/review">View Deal</a>
          </div>
        </div>
      </div>
    </div>
  </div>

Here is the code of service:

  GetRecommendedHotels(latitude, longitude) {
    return this.http.get('http://localhost:3000/app/hotels/Lahore/5')
      .map((response: Response) => {
        const gethotels = response.json().obj;
        console.log(gethotels);

        for (const hotel of gethotels) {
          this.transformedhotels.push(new Hotel(hotel.Name, hotel.Location, hotel.Price, hotel.Rating,  hotel.TotalRooms, hotel.FreeRooms, hotel.Image));
        }
        this.hotels = this.transformedhotels;
        return this.transformedhotels;
      })
      .catch((error: Response) => Observable.throw(error));
  }

Fetching code(In 'Hotel' component constructor)

  constructor(private hotelService: HotelService) {

    this.hotelService.GetRecommendedHotels(this.latitude, this.longitude).subscribe((hotels: Hotel[]) => {
      this.recommendedHotels = hotels;
      console.log('calling1');
    });
  }

Can anyone suggest me a better way?

1

There are 1 best solutions below

0
On

You are pushing latest data in existing array, clear existing array whenever you get updated data from back-end.

GetRecommendedHotels(latitude, longitude) {
    return this.http.get('http://localhost:3000/app/hotels/Lahore/5')
      .map((response: Response) => {
        const gethotels = response.json().obj;
        this.transformedhotels = []; <==============================
        console.log(gethotels);

        for (const hotel of gethotels) {
          this.transformedhotels.push(new Hotel(hotel.Name, hotel.Location, hotel.Price, hotel.Rating,  hotel.TotalRooms, hotel.FreeRooms, hotel.Image));
        }
        this.hotels = this.transformedhotels;
        return this.transformedhotels;
      })
      .catch((error: Response) => Observable.throw(error));
}