Building Angular2 Image Search with External API: Component Architecture Help Needed

Component Structure Issues in Angular2 Image Search App

I’m new to Angular2 and working on an image search application that connects to an external API. I’m trying to break down my code into separate components but running into problems.

Right now I have a working version that displays all results in one component, but I want to create individual components for each image result. Maybe even show a random one each time. I created the separate component but can’t figure out how to wire everything together properly.

The app works fine when I keep everything in one component, but breaks when I try to split it up. Since I’m just starting with Angular2, I’d appreciate any guidance on the right approach.

Main Application Component

import { Component } from '@angular/core';
import { Http, Response } from '@angular/http';
import { ImageItemComponent } from '../image-item/image-item.component';

@Component({
  selector: 'search-app',
  templateUrl: './search.component.html',
  styleUrls: ['./search.component.css']
})

export class SearchComponent {
  appTitle = 'ImageFinder';
  httpClient: Http;
  imageData: string;

  apiEndpoint = 'http://api.example.com/v1/images/search?key=abc123&query=';

  constructor(imageComp: ImageItemComponent){
    // trying to inject component here
  }

  searchImages(inputField: HTMLInputElement): void {
    console.log(`Search term: ${inputField.value}`);
    var requestUrl = this.apiEndpoint + inputField.value;

    this.httpClient.request(requestUrl)
        .subscribe((response: Response) => {
              this.imageData = response.json().data;
              console.log(this.imageData);
        });
  }
}

Module Configuration

import { BrowserModule } from '@angular/platform-browser';
import { NgModule } from '@angular/core';
import { Http, Headers, HttpModule, URLSearchParams } from '@angular/http';
import { SearchComponent } from './search.component';
import { ImageItemComponent } from '../image-item/image-item.component';

@NgModule({
  declarations: [
    SearchComponent,
    ImageItemComponent
  ],
  imports: [
    BrowserModule,
    HttpModule
  ],
  providers: [],
  bootstrap: [SearchComponent]
})
export class AppModule { }

Individual Image Component

import { Component, OnInit, Input } from '@angular/core';
import { Http, Response } from '@angular/http';

@Component({
  selector: 'image-item',
  templateUrl: './image-item.component.html',
  styleUrls: ['./image-item.component.css']
})
export class ImageItemComponent implements OnInit {
  @Input() imageResult;
  sourceUrl: string;
  apiBase = 'http://api.example.com/v1/images/search?key=xyz789&q=';
  results = [];
  
  constructor(private httpService: Http) { }

  fetchImage(query) {
    return this.httpService.get('http://api.example.com/v1/images/search?key=def456&q=' + query + '&count=1&lang=en')
  }
  
  ngOnInit() {
    this.sourceUrl = 'http://api.example.com/v1/images/search?key=xyz789&q=';
  }
}

Any tips on how to properly connect these components would be awesome!

You can’t inject one component into another through the constructor - that’s not how Angular works. Components talk to each other through inputs, outputs, and services.

Here’s how to fix it:

First, move your HTTP logic to a service. This keeps components clean and makes testing way easier.

@Injectable()
export class ImageSearchService {
  constructor(private http: Http) {}
  
  searchImages(query: string) {
    return this.http.get(`${this.apiEndpoint}${query}`);
  }
}

In SearchComponent, inject the service and store results:

export class SearchComponent {
  images: any[] = [];
  
  constructor(private imageService: ImageSearchService) {}
  
  searchImages(inputField: HTMLInputElement) {
    this.imageService.searchImages(inputField.value)
      .subscribe(response => {
        this.images = response.json().data;
      });
  }
}

In your template, loop through results and pass data down:

<image-item 
  *ngFor="let image of images" 
  [imageResult]="image">
</image-item>

I’ve built this exact pattern tons of times. Keep it simple - parent fetches data, children display it.

This video explains Angular components really well:

Also, ditch the HTTP logic from ImageItemComponent since you’re already fetching in the parent. Each component should do one thing.