Conduit用户可以关注和取消关注其他用户的资料。服务器API暴露了这样做的端点。因此,我们需要为我们的Profile服务添加follow和unfollow方法。

为ProfileService添加关注和取消关注方法

src/app/shared/services/profiles.service.ts

  1. [...]
  2. + follow(username: string): Observable<Profile> {
  3. + return this.apiService.post('/profiles/' + username + '/follow')
  4. + }
  5. +
  6. + unfollow(username: string): Observable<Profile> {
  7. + return this.apiService.delete('/profiles/' + username + '/follow')
  8. + }
  9. +
  10. }

很好!现在让我们在ApiService中建立DELETE函数。

为我们的ApiService添加delete()

src/app/shared/services/api.service.ts

  1. [...]
  2. delete(path): Observable<any> {
  3. return this.http.delete(`${environment.api_url}${path}`, { headers: this.setHeaders() })
  4. .catch(this.formatErrors)
  5. .map((res:Response) => res.json());
  6. }

现在让我们创建一个Follow按钮组件来调用这些方法。

创建FollowButtonComponent

src/app/shared/buttons/follow-button.component.html

  1. <button
  2. class="btn btn-sm action-btn"
  3. [ngClass]="{ 'disabled': isSubmitting,
  4. 'btn-outline-secondary': !profile.following,
  5. 'btn-secondary': profile.following }"
  6. (click)="toggleFollowing()">
  7. <i class="ion-plus-round"></i>
  8. &nbsp;
  9. {{ profile.following ? 'Unfollow' : 'Follow' }} {{ profile.username }}
  10. </button>

src/app/shared/buttons/follow-button.component.ts

  1. import { Component, EventEmitter, Input, Output } from '@angular/core';
  2. import { Router } from '@angular/router';
  3. import { Profile } from '../models';
  4. import { ProfilesService, UserService } from '../services';
  5. @Component({
  6. selector: 'follow-button',
  7. templateUrl: './follow-button.component.html'
  8. })
  9. export class FollowButtonComponent {
  10. constructor(
  11. private profilesService: ProfilesService,
  12. private router: Router,
  13. private userService: UserService
  14. ) {}
  15. @Input() profile: Profile;
  16. @Output() onToggle = new EventEmitter<boolean>();
  17. isSubmitting = false;
  18. toggleFollowing() {
  19. this.isSubmitting = true;
  20. this.userService.isAuthenticated.subscribe(
  21. (authenticated) => {
  22. // Not authenticated? Push to login screen
  23. if (!authenticated) {
  24. this.router.navigateByUrl('/login');
  25. return;
  26. }
  27. // Follow this profile if we aren't already
  28. if (!this.profile.following) {
  29. this.profilesService.follow(this.profile.username)
  30. .subscribe(
  31. data => {
  32. this.isSubmitting = false;
  33. this.onToggle.emit(true);
  34. },
  35. err => this.isSubmitting = false
  36. );
  37. // Otherwise, unfollow this profile
  38. } else {
  39. this.profilesService.unfollow(this.profile.username)
  40. .subscribe(
  41. data => {
  42. this.isSubmitting = false;
  43. this.onToggle.emit(false);
  44. },
  45. err => this.isSubmitting = false
  46. );
  47. }
  48. }
  49. )
  50. }
  51. }

通过桶和通过共享模块导出FollowButton。

为buttons文件夹创建一个新的桶。

src/app/shared/buttons/index.ts

  1. export * from './follow-button.component';

并将 buttons 桶导出到主 /shared 桶中。

src/app/shared/index.ts

  1. +export * from './buttons';
  2. export * from './layout';
  3. export * from './list-errors.component';
  4. export * from './models';
  5. [...]

让我们在共享模块中导入并声明新的按钮。

src/app/shared/shared.module.ts

  1. [...]
  2. import { HttpModule } from '@angular/http';
  3. import { RouterModule } from '@angular/router';
  4. +import { FollowButtonComponent } from './buttons';
  5. import { ListErrorsComponent } from './list-errors.component';
  6. import { ShowAuthedDirective } from './show-authed.directive';
  7. [...]
  8. RouterModule
  9. ],
  10. declarations: [
  11. + FollowButtonComponent,
  12. ListErrorsComponent,
  13. ShowAuthedDirective
  14. ],
  15. exports: [
  16. CommonModule,
  17. + FollowButtonComponent,
  18. FormsModule,
  19. ReactiveFormsModule,
  20. HttpModule,
  21. [...]

现在我们只需把它放在个人资料页面上,所有的功能就可以使用了!

src/app/profile/profile.component.html

  1. [...]
  2. <img [src]="profile.image" class="user-img" />
  3. <h4>{{ profile.username }}</h4>
  4. <p>{{ profile.bio }}</p>
  5. + <follow-button
  6. + [hidden]="isUser"
  7. + [profile]="profile"
  8. + (onToggle)="onToggleFollowing($event)">
  9. + </follow-button>
  10. <a [routerLink]="['/settings']"
  11. [hidden]="!isUser"
  12. class="btn btn-sm btn-outline-secondary action-btn">
  13. [...]

你可以将你的代码与Github上的有效代码进行比较,或者在本地检查分支:

  1. git checkout m-3