现在用户可以登录到我们的应用程序,让我们允许他们更新他们的设置。我们需要创建一个新的页面,该页面有一个连接到UserService的update方法的表单,我们将建立一个新的页面。我们还将在这个页面的底部包含一个注销按钮,它需要调用UserService的purgeAuth方法。

创建SettingsComponent

src/app/settings/settings.component.html

  1. <div class="settings-page">
  2. <div class="container page">
  3. <div class="row">
  4. <div class="col-md-6 offset-md-3 col-xs-12">
  5. <h1 class="text-xs-center">Your Settings</h1>
  6. <list-errors [errors]="errors"></list-errors>
  7. <form [formGroup]="settingsForm" (ngSubmit)="submitForm()">
  8. <fieldset [disabled]="isSubmitting">
  9. <fieldset class="form-group">
  10. <input class="form-control"
  11. type="text"
  12. placeholder="URL of profile picture"
  13. formControlName="image" />
  14. </fieldset>
  15. <fieldset class="form-group">
  16. <input class="form-control form-control-lg"
  17. type="text"
  18. placeholder="Username"
  19. formControlName="username" />
  20. </fieldset>
  21. <fieldset class="form-group">
  22. <textarea class="form-control form-control-lg"
  23. rows="8"
  24. placeholder="Short bio about you"
  25. formControlName="bio">
  26. </textarea>
  27. </fieldset>
  28. <fieldset class="form-group">
  29. <input class="form-control form-control-lg"
  30. type="email"
  31. placeholder="Email"
  32. formControlName="email" />
  33. </fieldset>
  34. <fieldset class="form-group">
  35. <input class="form-control form-control-lg"
  36. type="password"
  37. placeholder="New Password"
  38. formControlName="password" />
  39. </fieldset>
  40. <button class="btn btn-lg btn-primary pull-xs-right"
  41. type="submit">
  42. Update Settings
  43. </button>
  44. </fieldset>
  45. </form>
  46. <!-- Line break for logout button -->
  47. <hr />
  48. <button class="btn btn-outline-danger"
  49. (click)="logout()">
  50. Or click here to logout.
  51. </button>
  52. </div>
  53. </div>
  54. </div>
  55. </div>

这与我们在AuthComponent中的做法类似。我们本质上是在创建一个大的表单并加载现有的数据,这样我们的用户就可以更新他们的信息。现在我们只需要把它连接到UserService中的更新方法。Profile页面还不存在,但我们将在下一章创建它。

src/app/settings/settings.component.ts

  1. import { Component, OnInit } from '@angular/core';
  2. import { FormBuilder, FormGroup } from '@angular/forms';
  3. import { Router } from '@angular/router';
  4. import { User, UserService } from '../shared';
  5. @Component({
  6. selector: 'settings-page',
  7. templateUrl: './settings.component.html'
  8. })
  9. export class SettingsComponent implements OnInit {
  10. user: User = new User();
  11. settingsForm: FormGroup;
  12. errors: Object = {};
  13. isSubmitting: boolean = false;
  14. constructor(
  15. private router: Router,
  16. private userService: UserService,
  17. private fb: FormBuilder
  18. ) {
  19. // create form group using the form builder
  20. this.settingsForm = this.fb.group({
  21. image: '',
  22. username: '',
  23. bio: '',
  24. email: '',
  25. password: ''
  26. });
  27. // Optional: subscribe to changes on the form
  28. // this.settingsForm.valueChanges.subscribe(values => this.updateUser(values));
  29. }
  30. ngOnInit() {
  31. // Make a fresh copy of the current user's object to place in editable form fields
  32. (<any>Object).assign(this.user, this.userService.getCurrentUser());
  33. // Fill the form
  34. this.settingsForm.patchValue(this.user);
  35. }
  36. logout() {
  37. this.userService.purgeAuth();
  38. this.router.navigateByUrl('/');
  39. }
  40. submitForm() {
  41. this.isSubmitting = true;
  42. // update the model
  43. this.updateUser(this.settingsForm.value);
  44. this.userService
  45. .update(this.user)
  46. .subscribe(
  47. updatedUser => this.router.navigateByUrl('/profile/' + updatedUser.username),
  48. err => {
  49. this.errors = err;
  50. this.isSubmitting = false;
  51. }
  52. );
  53. }
  54. updateUser(values: Object) {
  55. (<any>Object).assign(this.user, values);
  56. }
  57. }

ngOnInit()中,我们将CurrentUser的信息复制到this.user中(在这里了解更多关于assign()的信息),然后用这些值更新settingsForm

当我们提交表单时,它会调用User Service中的一个更新函数,我们需要建立这个函数。

在用户服务中建立更新函数

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

  1. [...]
  2. // Update the user on the server (email, pass, etc)
  3. update(user): Observable<User> {
  4. return this.apiService.put('/user', { user })
  5. .map(data => {
  6. // Update the currentUser observable
  7. this.currentUserSubject.next(data.user);
  8. return data.user;
  9. });
  10. }

我们需要在ApiService中建立一个put函数来更新用户的信息。

在我们的ApiService中添加以下put()函数

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

只有已登录的用户才能访问设置页面。因此,我们将使用我们在上一章制作的AuthGuard。

创建设置模块并实现AuthGuard

src/app/settings/settings.module.ts

  1. import { ModuleWithProviders, NgModule } from '@angular/core';
  2. import { RouterModule } from '@angular/router';
  3. import { SettingsComponent } from './settings.component';
  4. import { AuthGuard, SharedModule } from '../shared';
  5. const settingsRouting: ModuleWithProviders = RouterModule.forChild([
  6. {
  7. path: 'settings',
  8. component: SettingsComponent,
  9. canActivate: [AuthGuard]
  10. }
  11. ]);
  12. @NgModule({
  13. imports: [
  14. SharedModule,
  15. settingsRouting
  16. ],
  17. declarations: [
  18. SettingsComponent
  19. ]
  20. })
  21. export class SettingsModule {}

最后我们需要做的是将它导入到AppModule中。

将SettingsModule导入到AppModule中。

src/app/app.module.ts

  1. [...]
  2. import { AppComponent } from './app.component';
  3. import { AuthModule } from './auth/auth.module';
  4. import { HomeModule } from './home/home.module';
  5. +import { SettingsModule } from './settings/settings.module';
  6. import {
  7. ApiService,
  8. AuthGuard,
  9. FooterComponent,
  10. HeaderComponent,
  11. JwtService,
  12. SharedModule,
  13. UserService
  14. } from './shared';
  15. [...]
  16. BrowserModule,
  17. AuthModule,
  18. HomeModule,
  19. rootRouting,
  20. SharedModule,
  21. + SettingsModule
  22. ],
  23. providers: [
  24. ApiService,
  25. AuthGuard,
  26. JwtService,
  27. UserService
  28. ],
  29. bootstrap: [AppComponent]
  30. [...]

现在我们可以导航到设置页面,并更新我们的用户数据!

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

  1. git checkout m-4