Sending the value of "username" between two components within Angular 2

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.

Answer №1

Utilizing a shared service would likely be the most efficient approach: Create a new service instance:

@Injectable()
export class YourSharedService {
    sharedUser: {
        // Define your properties here... for example
        username: 'string'
    };
}

Next, inject this service in both the parent and child components to access it within your components:

constructor(private yourSharedService: YourSharedService......) {  }

In your login component, assign the user to this newly created shared service so it can be accessed in all injected components:

assign:

this.yourSharedService.sharedUser = yourUserObject

You can then access the user in your components like this:

localUserObject = this.yourSharedService.sharedUser;

Additionally, note that using @Input works well when your child component is not on a separate route, but if it is behind a different route, utilizing a shared service is recommended :)

Shared services facilitate bi-directional communication; any changes made to the user properties in one component and saved in the shared service will automatically update other components that share the same object, ensuring consistent information across components, even when transitioning between them.

Answer №2

To improve your application's structure, consider creating a dedicated user service to manage user information post-login. This service can then be injected into your chat component using the @Injectable() decorator within the constructor:

constructor(public userService: UserService)
. You can then access the user info in your template with: User: {{ userService.username }}.

Similar questions

If you have not found the answer to your question or you are interested in this topic, then look at other similar questions below or use the search

Guide to utilizing @types/node in a Node.js application

Currently, I am using VSCode on Ubuntu 16.04 for my project. The node project was set up with the following commands: npm init tsc --init Within this project, a new file named index.ts has been created. The intention is to utilize fs and readline to read ...

Using JavaScript to transform JSON information into Excel format

I have tried various solutions to my problem, but none seem to fit my specific requirement. Let me walk you through what I have attempted. function JSONToCSVConvertor(JSONData, ReportTitle, ShowLabel) { //If JSONData is not an object then JSON.parse will ...

The Typescript Module augmentation seems to be malfunctioning as it is throwing an error stating that the property 'main' is not found on the type 'PaletteColorOptions'

Recently, I've been working with Material-UI and incorporating a color system across the palette. While everything seems to be running smoothly during runtime, I'm facing a compilation issue. Could someone assist me in resolving the following err ...

What is the best way to renew an access token with axios?

I have been struggling to understand the concept of refreshing tokens after reading numerous articles on the topic. They all seem too convoluted for me to grasp. Could someone please simplify it for me? Here is an overview of what I am trying to achieve: ...

Error in Angular 2: Uncaught Promise TypeError - Unable to access property 'title' of undefined

Whenever I attempt to include a text input field with dual binding in my App, the following error pops up: ERROR Error: Uncaught (in promise): TypeError: Cannot read property 'title' of undefined TypeError: Cannot read property 'title&ap ...

How to retrieve the user-agent using getStaticProps in NextJS

Looking to retrieve the user-agent within getStaticProps for logging purposes In our project, we are implementing access and error logs. As part of this, we want to include the user-agent in the logs as well. To achieve this, we have decided to use getSta ...

Abstraction of middleware functions

After reviewing my middleware Express functions, I realized that there is repeated code. The first function is as follows: const isAdmin = async (req, res, next) => { try { const requestingUser = await knex('users') ...

What could be causing the "AJAX data not defined" error

Attempting to make an Ajax post request to the root directory on my Express server. By simply using the HTML form and submitting an artist name, I successfully receive a response back and can send the information to the client without any issues... As se ...

Using Node.js and TypeScript to define custom data types has become a common practice among developers

I offer a variety of services, all yielding the same outcome: type result = { success: boolean data?: any } const serviceA = async (): Promise<result> => { ... } const serviceB = async (): Promise<result> => { ... } However, th ...

Tips for Angular 14: How to clearly define a form control as not being undefined

Consider a scenario with a form setup like this: searchForm = new FormGroup({ SearchBox = new FormControl<string>('', {nonNullable: true}); )} Now, when attempting to extract the value from the form field using this code snippet: thi ...

creating an interactive element that seamlessly integrates with a dynamic background image slideshow

Struggling to make this work correctly as a newbie in javascript. I need the background image to slide upon hover and stay active on its selected div when clicked. The html, css, and javascript I have currently work fine - when the user clicks on a div, a ...

Revive the design of a website

As I work on creating my own homepage, I came across someone else's page that I really liked. I decided to download the page source and open it locally in my browser. However, I noticed that while the contents were all there, the style (frames, positi ...

Utilizing $.Deferred() in a loop of nested ajax requests

I have spent countless hours searching for solutions to my problem, but I am still hopeful that someone out there has a solution. The issue at hand is being able to receive a notification once function a() has finished its execution. The challenge lies in ...

The Vue ChartJS fails to display properly after the page is refreshed

Although this issue may appear to be a common one, some of the suggested solutions are outdated or no longer functional. My objective is to ensure that the chart remains responsive even after the page reloads. I attempted to implement the solution provided ...

The Next.js build encountered an error - unable to locate function in next/script module

While constructing a CMS using next.js, one of the key components is media management through Cloudinary. The integration of the Cloudinary Media Library widget was successful during development using next/script. However, an error has now emerged that pre ...

The Angular template loads and renders even before the dynamic data is fetched

I'm encountering a frustrating issue where the page loads before the data is retrieved. When I log the names in $(document).ready(), everything appears correct without any errors in the console. However, the displayed html remains empty and only shows ...

Hidden warning to React-select for being uncontrolled

I've integrated react-select into my code: import React, {Component} from 'react'; import Select, {createFilter} from 'react-select'; let _ = require('underscore') class Test extends Component { constructor(props) ...

Sorting a parent array in AngularJS using a child array's Date field as the basis

I have an array of arrays of objects with the following structure: parentArray = [ [{id:1, date:1505020200000}, {id:4, date:1505020200000 }], [{id:2, date:1504681500000}], [{id:3, date:1504671000000}, {id:20, date:1504671000000}] ] Each nested array cont ...

Create a smooth scrolling effect for a div with a fixed position

Having trouble scrolling a fixed position div on the page? Are you using this jquery script: $('html, body').animate({ scrollTop: $(".example").offset().top }, 750); I had to set the body overflow property to hidden for another issue. The ...

Disabling the ripple effect on the primary action in React Material lists: A Step-by-Step

I was attempting to include two action buttons at the opposite ends of a list component. https://i.stack.imgur.com/juv8F.gif When clicking on the secondary action (delete icon on the right), the ripple effect is confined to just the icon. On the othe ...