Linking Between Components

Now that the application has several components to handle, we need some way of linking between them. To do this, we use the routerLink directive, which allows us to use regular <a> tags like usual, but also hooks in all the niceties from the router. Much like the href attribute, we pass the route we want to link to:

 <a routerLink=​"edit/{{photo.id}}"​>Edit</a>

The routerLink directive is not limited to just anchor tags—it can be attached to virtually any clickable element. Open search-header.component.html and add a routing bar with two routerLink attributes, which allow the user to navigate between the pages of this app.

 <div class=​"container"​>
  <div class=​"row center-text"​>
  <div class=​"btn-group"​>
  <button type=​"button"​ class=​"btn btn-default"
  routerLink=​"/"​>Search Photos</button>
  <button type=​"button"​ class=​"btn btn-default"
  routerLink=​"/savedphotos"​>My Saved Photos</button>
  </div>
  </div>
 </div>

Now that there’s a route to SavedListComponent, it’s time to make that component do something.

Displaying a List of Saved Photos

This component can fetch all saved photos from the backend, display them as a list, and let the user select photos to edit individually. It has a lot in common with the ResultsListComponent, though there are a few differences once you get into the details. The two main differences are that the photo variable is now an object (instead of a string), and the button below the photo routes to the edit photo page.

The next chunk of the project will exercise the skills you learned from building the ResultsListComponent, so I recommend that you attempt to build this component out before you take a peek at the completed code below. The one hint you will need is that the endpoint to retrieve all saved photos is located at http://localhost:3000/api/ng2ajax/savedPhotos.

Ready to check your work?

The first thing is to add a method to PhotosService that fetches a list of all saved photos.

 getSavedPhotos() {
 return​ ​this​.http.​get​<IPhoto[]>(​this​.api + ​'/savedPhotos'​);
 }

After that’s added, you need to inject PhotosService into SavedListComponent and add an observable property representing that call.

 export​ ​class​ SavedListComponent ​implements​ OnInit {
 
  savedPhotos$: Observable<IPhoto[]>;
 constructor​(​private​ photosService: PhotosService) { }
 
  ngOnInit() {
 this​.savedPhotos$ = ​this​.photosService.getSavedPhotos();
  }
 }
Joe asks:
Joe asks:
Why Can’t I Just Call getSavedPhotos Directly?

It would reduce the boilerplate if we could just call getSavedPhotos directly in the view, but this doesn’t work out the way we want. Whenever there’s a change, Angular needs to double-check that the values in the view layer haven’t changed. If getSavedPhotos is called in the view, Angular dutifully calls it whenever Angular checks for changes. This change detection cycle can be triggered by many things, one of which is an AJAX call completing. So if checking the view makes an AJAX call, and every time an AJAX completes, the view is checked, calling getSavedPhotos directly will result in an infinite loop and a very sad user. You’ll read more about this change detection cycle (and the observables behind it) in Chapter 8, Advanced Angular.

Finally, add the observable to the view (including the async pipe):

 <div ​*​ngFor=​"let photo of savedPhotos$ | async"​ class=​"result-container"​>
  <img ​[​src​]="​photo​.​url​"​ class=​"results-img"​ />
  <button class=​"btn btn-default results-btn"
  routerLink=​"/edit/{{ photo.id }}"​>Edit</button>
 </div>

Now users can see an overview of all the photos they’ve saved so far. The last major task is to build out a page to edit individual photos.

..................Content has been hidden....................

You can't read the all page of ebook, please click here login for view all page.
Reset
18.223.170.223