balajivaishnav
balajivaishnav

Reputation: 2893

Angular 2, Cant able to access a variable in one Component from another Component

Sorry if this is a duplicated question, I have searched solution throughout the Web can't able to find any so am posting it, Am trying to access a variable from one component inside another component

What I have Tried

I have created a model of object type and have set the value inside a component A method, and tried to access that model object from component B so that I can set the value for the Component B Elements, but getting object as undefined

Problem

Component A is loaded first in browser, where it contains a table on click of the table row am getting the row data as object and setting that object to a Model which contains a similar structure object and I can able to get the object value in Component, whereas I tried to call the model from a Component B so that I can access the object value. but am getting the object value as undefined this is due to the Component B is a Modal which is Called inside the Component A Template.

Component A

 public rowSelected:boolean = true;
 constructor(public users : User ) {}
  getRowData(rowIndex: number, rowData: any): void { 
        this.rowSelected = $(rowIndex).hasClass('selected');
        console.log(rowData);
        this.users= rowData.FirstName;
        console.log(this.users); // can able to get the object value
    }

Component A Template

<div bsModal #editUserModal="bs-modal" class="modal fade" role="dialog" aria-hidden="true">
    <div class="modal-dialog modal-lg">
        <div class="modal-content">
            <div class="modal-header">
                <button class="close" aria-label="Close" type="button" (click)="editUserModal.hide()">
                    <span aria-hidden="true">&times;</span>
                </button>
                <h5 class="modal-title"><b>Edit User</b></h5>
            </div>
            <div class="modal-body">
                <componenetB #edituserDiv></componenetB>
            </div>
            <div class="modal-footer">
                <button class="btn btn-primary btn-sm  confirm-btn gap0" type="button" (click)="edituserDiv.EditUserSubmit()">Submit</button>
                <button type="button" class="btn btn-default btn-sm gap-left10 gap0" type="button" (click)="editUserModal.hide()">Close</button>
            </div>
        </div>
    </div>
</div>

Model

export class User {
    UserName: any
    Password: any
    FirstName: any
    MiddleName: any
    LastName: any
    Status: any
    Locked: any
    Active: any
    CreatedOn: any
    LastModified: any

}

Component B

export class Component B   { 

    constructor(public userz : User) {     
console.log(this.userz) // Object Value is Undefined
    }

}

Please help me to resolve this issue, thanks in advance

Upvotes: 5

Views: 17389

Answers (4)

Imants Volkovs
Imants Volkovs

Reputation: 836

I hope I understand your question. If this answers you question remember to mark it as answer.

If you have a component (A - parent) which has child component (B - child), then you can use Input/Output decorators to communicate between them.

Child component has event property userSelected, it will fire event when emit(value?: T): void method will be called. Parent component will receive event here - (userSelected)="onUserSelect($event) where $event contains value passed to emit method. So it can be used in parent component

More detailed description here: http://learnangular2.com/outputs/

Parent:

@Component({
   selector: 'component-a',
   template:'<component-b (userSelected)="onUserSelect($event)"></component-b>'
})
export class AComponent{
    selectedUser: User;
    onUserSelect(user: User){
       this.selectedUser = user;
    }
}

Child:

@Component({
   selector: 'component-b'
})
export class BComponent {
   @Output() userSelected: EventEmitter<User>;

   rowClicked(user: User): void {
       this.userSelected.emit(user);
   }
}

UPDATE - Input version

According to Component A template, component B is child of component A

Further I go into your implementation, I get the feeling that whole logic is weird. As I understand, you have a table of users in Component A, then when a row is selected modal window pops up (component B) where you manipulate user details. So template for component A should look like this (simplified version):

<div class="modal-body">
   <componenetB [selectedUser]="selectedUser"></componenetB>
</div>

Then for B component define input variable with same name as used in A template

@Component({
   selector: 'component-b'
})
export class BComponent {
   @Input() selectedUser: User;

   //Further your logic using selectedUser variable
   //If need to return modified selectedUser to A component, use Output
}

Well it seems that you miss code logic to select user. I guess you should have something similar to this, that is just an example. You should pass whole object to component B.

<table>
   <tr*ngFor="let user of users">
      <td (onClick)="openBModal(user)">{{user.UserName}}</td>
   </tr>
</table>

To give more precise answer please provide plunker with your example, with this little information is hard to understand what are you going to achieve

Upvotes: 0

AVJT82
AVJT82

Reputation: 73377

Use @Input when you want to pass data from parent to child. Here I assume users is an array. If not, adjust the type accordingly.

So in your parent template:

<componenetB [users]="users"></componenetB>

From your child (component B), do not inject User in constructor. Use @Input instead:

export class Component B   { 
    @Input users: User[];

    constructor() { }
}

So that you do not get undefined error if the users is actually set later, just instantiate the users in your parent, so that it won't be undefined, while it waits for values to be set:

users: User[] = [];

Here is a demo, which simulates the values of users are set at a later point. Just click the button and the values will appear in child, values that are set in the parent.

Plunker

Upvotes: 5

Ghanshyam Singh
Ghanshyam Singh

Reputation: 1381

Component A

import {Component,EventEmitter} from "@angular/core";
import {User} from "User.Model";

@Component({
   selector: 'component-A',
   outputs :["selectedUser"],
   templateUrl:''
})

export class AppComponent{
 selectedUser : new EventEmitter<User>;
 public rowSelected:boolean = true;
 constructor(public users : User ) {}
 getRowData(rowIndex: number, rowData: any): void { 
        this.rowSelected = $(rowIndex).hasClass('selected');
        console.log(rowData);
        this.users= rowData.FirstName;
        this.selectedUser.emit(this.users);
    }
}

Component B Html

<component-a (selectedUser)="PrintUserInfo($event)"></component-a>

Component B.ts

// skipping some code
export class BComponent{
     PrintUserInfo(user :User): void {
       console.log("Name :" + user.Name);
   }
}

Upvotes: 0

Alejandro
Alejandro

Reputation: 1

I can't see the binding. May be you are missing something like <hero-detail [hero]="selectedHero"></hero-detail>

Upvotes: 0

Related Questions