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

The mermaidAPI.initialize function in Angular does not support the maxTextSize option

I'm currently encountering an issue while attempting to utilize mermaidAPI.initialize in an Angular environment. ngOnInit(): void { this.windowHeight = window.innerHeight; mermaidAPI.initialize({ maxTextSize: 1000000, logLevel: & ...

Designed radio buttons failing to activate when focused using a keyboard

I'm facing an issue with radio input buttons that I've dynamically added to a div using jQuery. They function properly when clicked with a mouse, but do not get activated when using the keyboard tab-focus state. NOTE: To style the radio buttons ...

Veracode Scan finds vulnerability in jQuery html method with Improper Neutralization of Script-Related HTML Tags in a Web Page error

Veracode has flagged the issue Improper Neutralization of Script-Related HTML Tags in a Web Page (Basic XSS) within the following line of code. $('#SummaryDiv').html(data); $.ajax({ url: 'Target_URL', type: &a ...

When it comes to assigning a background to a div using jQuery and JSON

I have been experimenting with creating a database using only JSON and surprisingly, it worked once I added a "js/" in the URL. However, my current issue lies with CSS. Let me elaborate. Here is the JSON data: [ { "title":"Facebook", ...

The initiation of jQuery animation through user interaction hinges on the completion of the preceding animation

In my project, I've designed a timeline that offers users the ability to zoom in and out by simply clicking on corresponding buttons. Since the timeline is too large to fit entirely on the screen, it is contained within a scrollable div. To ensure tha ...

Tips on retrieving complete information from mongoose when the schema contains a reference

I have a schema that includes [content, name, email], and I need to retrieve all three data fields and render them on the frontend simultaneously. Can you provide an example of JavaScript code that accomplishes this? const UserSchema = new mongoose.Schem ...

An unusual problem stemming from jQuery/AJAX arises when variables within a function fail to update while a click

I've been struggling with a small issue for the past three days that I just can't seem to resolve. It doesn't seem to be a coding error, but rather a misunderstanding of variables and why the onClick event isn't functioning properly. H ...

Issue with Jquery Drag and Drop functionality, navigate to a different page

I am trying to incorporate a page with js from quotemedia.com using Jquery. When I insert the js into the sortable, and then drag and drop the element containing the js, it suddenly switches to full page display. This issue occurs in Firefox, but IE works ...

What steps should I take to ensure that clicking this button triggers the API request and returns the data in JSON format?

I'm attempting to have the button with id 'testp' return an api request in json format, however it seems to not be functioning properly. You can find the HTML code link here: https://github.com/atullu1234/REST-API-Developer-1/blob/main/js-bu ...

The Parse.com cloudcode refuses to enter the success or error state

Running this code in my Parse cloud, I noticed that when I call it from my app, it never enters the success or error statement. Could it be because the .save method isn't working? Any assistance would be greatly appreciated :) This is how I invoke t ...

Locating Undiscovered Users within mongodb

I have created a post collection where each user who marks a post as read has their user ID added to an array within the post document. Now, I am attempting to identify which users have not read certain posts by utilizing the $nin function while iteratin ...

Implement necessary validation for the country code selection on the dropdown menu using the intl-tel-input jQuery plugin

Check out the intl-tel-input plugin here Currently, I am utilizing this plugin and attempting to implement required validation on the country code drop-down. However, the plugin seems to be restricting me from achieving this. I have made several attempts ...

The caching mechanism in IE 11 is preventing Ajax from loading and displaying data

Utilizing Ajax to verify data and display it on the page, alongside implementing varnish cache. The data appears correctly on all web browsers, with the exception of IE 11, unless the varnish cache is disabled. function checkMyData() { var surl = 'in ...

What is the best way to ensure an observable has finished before retrieving a value?

Looking at the function provided below: public getAssemblyTree(id: number) { .... const request = from(fetch(targetUrl.toString(), { headers: { 'responseType': 'json' }, method: 'GET' })); request.sub ...

Ways to invoke a function within a React Material-UI component

Currently, I am in the process of setting up a chat system that allows users to add emojis. To achieve this feature, I have devised a function that produces a component containing both text and an image. Here is the function I have implemented: test: fu ...

Encountering a problem when trying to dynamically change the value in a dropdown menu with Angular.js

Having an issue where two drop down lists have the same value. When I set a value to the first drop down list, the second one also takes that value. Below is my code for reference: <div class="col-md-6"> <div class="input-group bmargindiv1 col-md ...

Populating dropdown menu with data fetched from an AJAX request

I've created a dropdown in my cshtml page: @( Html.Kendo().DropDownList().Name("ddlCode").OptionLabel("Select Code...").BindTo(@ViewBag.dropDown) .DataTextField("Title") .DataValueField("domainCode") The dropdown is bound up ...

The 'items' property cannot be linked to 'virtual-scroller' as it is not a recognized attribute

I'm currently facing an issue with integrating virtual scroll into my Ionic 4 + Angular project. Previously, I relied on Ionic's implementation of virtual scroll (ion-virtual-scroll) which worked well initially. However, I encountered a major dr ...

Problem with Raphael Sketch and Request to Ajax

Utilizing Raphael.js and jQuery Ajax, I am attempting to display some dots (circles) on the map in this [Demo][1]. I have a PHP file called econo.php which looks like this: <?PHP include 'conconfig.php'; $con = new mysqli(DB_HOST,DB_USER,DB_P ...

Tips for setting a uniform width for all bars in apexcharts bar column width

When working with dynamic data, the length of the data should also be variable. For instance, if the data has a length of 24, the column width should be 35px; similarly, even if the data has a length of 2, the column width should still be 35px. Apexchart ...