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.