Angular 2, невозможно получить доступ к переменной в одном компоненте из другого компонента

Извините, если это дублированный вопрос, я искал решение в Интернете, но не смог его найти, поэтому публикую его. Я пытаюсь получить доступ к переменной из одного компонента внутри другого компонента.

Что я пробовал

Я создал модель типа объекта и установил значение внутри метода компонента A и попытался получить доступ к этому объекту модели из компонента B, чтобы я мог установить значение для элементов компонента B, но получить объект как неопределенное

Проблема

Компонент A загружается первым в браузере, где он содержит таблицу при щелчке строки таблицы. Я получаю данные строки как объект и устанавливаю этот объект в модель, которая содержит объект аналогичной структуры, и я могу получить значение объекта в компоненте , тогда как я пытался вызвать модель из компонента B, чтобы получить доступ к значению объекта. но я получаю значение объекта как неопределенное, это связано с тем, что компонент B является модальным, который вызывается внутри шаблона компонента 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
    }

Шаблон компонента A

<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>

Модель

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

}

Компонент Б

export class Component B   { 

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

}

Пожалуйста, помогите мне решить эту проблему, заранее спасибо


person balajivaishnav    schedule 11.04.2017    source источник
comment
angular.io/docs/ts/latest/tutorial/toh-pt3. html   -  person Deblaton Jean-Philippe    schedule 11.04.2017
comment
@DeblatonJean-Philippe, не могли бы вы указать, что не так?..   -  person balajivaishnav    schedule 11.04.2017
comment
@DeblatonJean-Philippe на самом деле устанавливаю данные при щелчке строки, поэтому изначально компонент B получает неопределенное значение, используя @input()   -  person balajivaishnav    schedule 11.04.2017
comment
Без @Input() и @Output вы не можете передавать данные между компонентами   -  person Ghanshyam Singh    schedule 11.04.2017
comment
я получаю сообщение об ошибке консоли, поскольку не могу прочитать свойство 'emit' неопределенного, любая идея   -  person balajivaishnav    schedule 11.04.2017


Ответы (4)


Используйте @Input, когда хотите передавать данные от родителя к дочернему. Здесь я предполагаю, что users - это массив. Если нет, измените тип соответствующим образом.

Итак, в вашем родительском шаблоне:

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

От вашего ребенка (компонент B) не вводите User в конструктор. Вместо этого используйте @Input:

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

    constructor() { }
}

Чтобы вы не получили ошибку undefined, если users на самом деле установлено позже, просто создайте экземпляр users в своем родителе, чтобы он не был неопределенным, пока он ожидает установки значений:

users: User[] = [];

Вот демонстрация, которая имитирует значения users, установленные позже. Просто нажмите кнопку, и значения появятся в дочернем, значения, которые установлены в родительском.

Плункер

person AJT82    schedule 11.04.2017
comment
но я устанавливаю данные внутри метода из компонента A - person balajivaishnav; 12.04.2017
comment
Что ж, это то, что он делает. Посмотрите внимательно на плунжер. Когда вы нажимаете кнопку в родительском, запускается setUsers, который устанавливает значения, а затем они отображаются в дочернем. - person AJT82; 12.04.2017
comment
Большое спасибо, приятель, твой ответ дал мне хорошую идею для завершения моей работы. - person balajivaishnav; 12.04.2017
comment
Не за что, рад, что смог помочь :) - person AJT82; 12.04.2017

Я не вижу привязки. Возможно, вы пропустили что-то вроде <hero-detail [hero]="selectedHero"></hero-detail>

person Alejandro    schedule 11.04.2017
comment
Я также пробовал это, я устанавливаю значение при щелчке строки таблицы, поэтому мой компонент B получает неопределенные данные, есть какое-либо представление об этом - person balajivaishnav; 11.04.2017

Компонент А

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);
    }
}

Компонент B HTML

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

Компонент B.ts

// skipping some code
export class BComponent{
     PrintUserInfo(user :User): void {
       console.log("Name :" + user.Name);
   }
}
person Ghanshyam Singh    schedule 11.04.2017
comment
не могли бы вы проверить свой код, я думаю, что это неправильно, мне нужно передать данные из компонента A в компонент B - person balajivaishnav; 11.04.2017
comment
И он работает нормально - person Ghanshyam Singh; 11.04.2017
comment
я получаю сообщение об ошибке консоли, поскольку не могу прочитать свойство 'emit' из неопределенного - person balajivaishnav; 11.04.2017
comment
selectedUser : new EventEmitter<User>; вы написали эту строку внутри своего класса? - person Ghanshyam Singh; 11.04.2017
comment
Я думаю, вы используете более старую версию Angular 2?.. потому что вывод является отдельным декоратором и не используется в декораторе компонентов. - person balajivaishnav; 12.04.2017
comment
Почему мне нужно использовать компонент A внутри моего компонента B? я уже использую компонент B внутри компонента A - person balajivaishnav; 12.04.2017

Надеюсь, я понял ваш вопрос. Если это отвечает на ваш вопрос, не забудьте пометить его как ответ.

Если у вас есть компонент (A - родительский), у которого есть дочерний компонент (B - дочерний), вы можете использовать декораторы ввода/вывода для связи между ними.

Дочерний компонент имеет свойство события userSelected, он сгенерирует событие, когда будет вызван метод emit(value?: T): void. Родительский компонент получит событие здесь - (userSelected)="onUserSelect($event), где $event содержит значение, переданное в метод emit. Таким образом, его можно использовать в родительском компоненте.

Более подробное описание здесь: http://learnangular2.com/outputs/

Родитель:

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

Ребенок:

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

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

ОБНОВЛЕНИЕ – введенная версия

В соответствии с шаблоном компонента A компонент B является дочерним по отношению к компоненту A.

Далее я углубляюсь в вашу реализацию, у меня возникает ощущение, что вся логика странная. Насколько я понимаю, у вас есть таблица пользователей в Компоненте А, затем при выборе строки появляется всплывающее модальное окно (компонент Б), в котором вы манипулируете данными пользователя. Таким образом, шаблон для компонента A должен выглядеть так (упрощенная версия):

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

Затем для компонента B определите входную переменную с тем же именем, что и в шаблоне A.

@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
}

Что ж, похоже, вам не хватает логики кода для выбора пользователя. Я думаю, у вас должно быть что-то похожее на это, это просто пример. Вы должны передать весь объект компоненту B.

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

Чтобы дать более точный ответ, пожалуйста, предоставьте plunker свой пример, с этой небольшой информацией трудно понять, чего вы собираетесь достичь.

person Imants Volkovs    schedule 11.04.2017
comment
Логика @MBalajivaishnav остается прежней, только наоборот. Это пример для вашей проблемы. Просто поменяйте компоненты, и вы получите желаемое решение. - person Imants Volkovs; 12.04.2017
comment
Я понимаю это, но если я переключу логику наоборот, я не смогу получить желаемый результат, на самом деле декоратор вывода используется для передачи данных от дочернего к родительскому компоненту, но я пытаюсь от родителя к дочернему, я не думаю, что вывод будет помогите мне, вместо этого мне нужно выбрать декоратор ввода - person balajivaishnav; 12.04.2017