I have a good understanding of nesting child components within parent components in Angular 2, but I'm a bit unclear on how to pass a single value from one component to another. In my scenario, I need to pass a username from a login component to a chat component so that it can be displayed in the chatbox. I assume the @Input() decorator is what I need to use here, but I'm not entirely sure how to implement it.
This is the code snippet from my login component HTML:
<div class="center-box">
<form name="form" class="form-fields" (ngSubmit)="f.form.valid && login()" #f="ngForm" novalidate>
<div class="form-group" [ngClass]="{ 'has-error': f.submitted && !username.valid }">
<input type="text" form autocomplete="off" class="form-control" name="username" [(ngModel)]="model.username" #username="ngModel" required />
<div *ngIf="f.submitted && !username.valid" class="help-block">Username is required</div>
</div>
<div class="form-group" [ngClass]="{ 'has-error': f.submitted && !password.valid }">
<input type="password" class="form-control" name="password" [(ngModel)]="model.password" #password="ngModel" required />
<div *ngIf="f.submitted && !password.valid" class="help-block">Password is required</div>
</div>
<div class="form-group">
<button class="submit-btn">Login</button>
</div>
</form>
<div align="center" [ngStyle]="{'color': 'red'}"><alert></alert></div>
</div>
And here's the TypeScript code for the login component:
import { AuthenticationService } from './../../data/authentication.service';
import { AlertService } from './../../data/alert.service';
import { Component, OnInit, Input } from '@angular/core';
import { Router } from '@angular/router';
@Component({
selector: 'app-login',
templateUrl: 'app/views/login/login.component.html',
styleUrls: ['app/views/login/login.component.css']
})
export class LoginComponent implements OnInit {
model: any = {};
loading = false;
username;
password;
constructor(
private router: Router,
private authenticationService: AuthenticationService,
private alertService: AlertService) { }
ngOnInit() {
// reset login status
this.authenticationService.logout();
}
login() {
this.loading = true;
this.authenticationService.login(this.model.username, this.model.password)
.subscribe(
data => {
this.router.navigate(['/']);
console.log('User logged in as: ' + this.model.username);
},
error => {
this.alertService.error(error);
this.loading = false;
});
}
}
Next, let's take a look at the chat component HTML:
<div class="centered-display" align="center">
<h3>User: {{username}}</h3>
<div *ngFor="let message of messages" class="message">
{{username}}: {{message.text}}
</div>
<input class="form-group" [(ngModel)]="message" (keypress)="eventHandler($event)">
<div class="spacing">
<button class="submit-btn" md-button (click)="sendMessage()">SEND</button>
</div>
</div>
Now, the TypeScript code for the chat component:
import { Router, ActivatedRoute } from '@angular/router';
import { ChatService } from './chat.service';
import { Component, OnInit, OnDestroy } from '@angular/core';
import { TabPage } from '../../ui/tab-navigation/tab-page';
@Component({
templateUrl: './chat.component.html',
styleUrls: ['./chat.component.less']
})
export class ChatComponent extends TabPage implements OnInit, OnDestroy {
username = '';
messages = [];
users = [];
routes;
connection;
userbase;
route;
message;
user;
constructor(private chatService:ChatService, router: Router, route: ActivatedRoute) {
super(router, route);
this._title = 'Chat Room';
this.addEventListener('paramsChange', function(params) {
this._title = 'Chat Room';
}.bind(this));
}
sendMessage() {
this.chatService.sendMessage(this.message);
this.message = '';
}
sendUser() {
this.chatService.sendUser(this.user);
this.user = '';
}
trackUser() {
this.chatService.trackUser(this.route);
console.log('A user just navigated to ' + this.route);
}
// For when user clicks "enter/return" to send message
eventHandler(event: KeyboardEvent): void {
if (event.key === 'Enter') {
this.chatService.sendMessage(this.message);
this.message = '';
}
}
ngOnInit() {
this.connection = this.chatService.getMessages().subscribe(message => {
this.messages.push(message);
});
this.userbase = this.chatService.getUsers().subscribe(user => {
this.users.push(user);
});
this.routes = this.chatService.getRoutes().subscribe(route => {
this.routes.push(route);
});
}
ngOnDestroy() {
this.connection.unsubscribe();
this.userbase.unsubscribe();
}
}
To bind and pass the value from the login component to the chat component, you'll need to properly utilize the @Input() decorator or find an alternative method to achieve this seamless data flow between components.