Add ProfileComponent and Routes

Now let's add profile component and its routes in this chapter.

We will add ChannelHeader, ChatAreaHeader, Profile, and Info components.

The ChannelHeaderComponent only shows the user name, when we click that name, the app will go to profile page to let us edit the page.

src/app/chat/components/channel-header.component.ts

import { Component, Input, Output, EventEmitter, ChangeDetectionStrategy } from '@angular/core';

@Component({
  selector: 'my-channel-header',
  changeDetection: ChangeDetectionStrategy.OnPush,
  styles: [`
    .wrapper {
      margin: 1rem;
      color: #C5D5DF;
    }

    .name {
      cursor: pointer;
    }
  `],
  template: `
    <div class="wrapper">
      <h3 class="name" (click)="onGoProfile()">{{name}}</h3>
    </div>
  `
})
export class ChannelHeaderComponent {
  @Input() name: string;
  @Output() goProfile = new EventEmitter<void>();

  private onGoProfile() {
    this.goProfile.emit(null);
  }
}

src/app/chat/components/chat.component.ts

// ...
import { ProfileService } from '../../profile/services/profile.service';

@Component({
  selector: 'my-chat',
  // ...
  template: `
    <!-- ... -->
    <my-channel-header
      [name]="profileService.currentUser.name"
      (goProfile)="onGoProfile()">
    </my-channel-header>
    <!-- ... -->
  `,
})
export class ChatComponent implements OnInit, OnDestroy {
  // ...

  constructor(
    // ...
    private profileService: ProfileService
  ) {}

  onGoProfile() {
    this.router.navigate(['/profile']);
  }
}

ProfileComponent is a smart component, which will be responsible to interact with UserService. It has only one child component InfoComponent.

window.history.back(); will help us go back to last page.

src/app/profile/components/profile.component.ts

import { Component } from '@angular/core';

import { ProfileService } from '../services/profile.service';

@Component({
  selector: 'my-profile',
  template: `
    <my-info
     [name]="profileService.currentUser.name"
     (updateProfile)="onUpdateProfile($event)">
    </my-info>
  `
})
export class ProfileComponent {
  constructor(
    private profileService: ProfileService
  ) {}

  private onUpdateProfile(name: string) {
    this.profileService.updateProfile(name);
    window.history.back();
  }
}

InfoComponent is a dumb component, it will show the user name, and will emit an event when user tries to update the name.

It is using reactive form which is similar to the form in the ChatAreaBottomComponent.

src/app/profile/components/info.component.ts

import { Component, OnInit, Input, Output, EventEmitter, ChangeDetectionStrategy } from '@angular/core';
import { FormBuilder, FormGroup, Validators } from '@angular/forms';

@Component({
  selector: 'my-info',
  changeDetection: ChangeDetectionStrategy.OnPush,
  template: `
    <form [formGroup]="profileForm" (ngSubmit)="onUpdateProfile()">
      <label>Name</label>
      <input formControlName="name" placeholder="name" />
      <button type="submit">Save changes</button>
    </form>
  `
})
export class InfoComponent implements OnInit {
  @Input() name: string;
  @Output() updateProfile = new EventEmitter<string>();

  profileForm: FormGroup;

  constructor(
    private fb: FormBuilder
  ) {}

  ngOnInit() {
    this.profileForm = this.fb.group({
      name: [this.name, Validators.required]
    });
  }

  private onUpdateProfile() {
    if (!this.profileForm.valid) return;

    this.updateProfile.emit(this.profileForm.value.name);
  }
}

src/app/profile/models/user.model.ts

export interface User {
  _id?: string,
  name: string
}

The user service provides the way to update the profile, in the future we will update to use real server.

src/app/profile/services/profile.service.ts

import { Injectable } from '@angular/core';

import { User } from '../models/user.model';

@Injectable()
export class ProfileService {
  currentUser: User = {
    _id: '0',
    name: 'Jack'
  };

  updateProfile(name: string): void {
    this.currentUser.name = name;
  }
}

We also need update ChatService to make sure using latest name when we send message.

src/app/chat/services/chat.service.ts

// ...
import { ProfileService } from '../../profile/services/profile.service';

@Injectable()
export class ChatService {
  constructor(
    private profileService: ProfileService
  ) {}

  // ...
  sendMessage(channelId: string, messageContent: string): void {
    const message = {
      // ...
      userId: this.profileService.currentUser._id,
      userName: this.profileService.currentUser.name,
      // ...
    };

    // ...
  }
}

src/app/app.module.ts

// ...
import { ChannelHeaderComponent } from './chat/components/channel-header.component';
import { ProfileComponent } from './profile/components/profile.component';
import { InfoComponent } from './profile/components/info.component';
import { ProfileService } from './profile/services/profile.service';

@NgModule({
  // ...
  declarations: [
    // ...
    ChannelHeaderComponent,
    InfoComponent,
    ProfileComponent,
    // ...
  ],
  providers: [
    // ...
    ProfileService
  ],
  // ...

Now your app should look like this:

Chat page:

Profile page:


Run the live example for this part.

results matching ""

    No results matching ""