부모에서 자식으로 이벤트를 내보내는 방법은 무엇입니까?


111

저는 현재 Angular 2를 사용 @Output() addTab = new EventEmitter<any>();하고 있습니다. 일반적으로 우리는 addTab.emit()부모 구성 요소에 이벤트를 내 보냅니다.

부모에서 자식으로 반대로 할 수있는 방법이 있습니까?


2
입력으로 전달 된 표현식의 값을 자식 구성 요소에 변경하면 자식 구성 요소가이를 가져옵니다 (그리고 ngOnChanges에 의해 알림). Observable이있는 공유 서비스를 사용하여 이벤트를 생성 할 수도 있습니다.
JB Nizet

답변:


192

RxJs를 사용하면 Subject부모 구성 요소에서를 선언하고 Observable자식 구성 요소 로 전달할 수 있으며 자식 구성 요소는 this Observable.

상위 구성 요소

eventsSubject: Subject<void> = new Subject<void>();

emitEventToChild() {
  this.eventsSubject.next();
}

부모 -HTML

<child [events]="eventsSubject.asObservable()"> </child>    

하위 구성 요소

private eventsSubscription: Subscription;

@Input() events: Observable<void>;

ngOnInit(){
  this.eventsSubscription = this.events.subscribe(() => doSomething());
}

ngOnDestroy() {
  this.eventsSubscription.unsubscribe();
}

13
또한이 접근 방식을 사용하여 이벤트와 함께 데이터를 전달할 수 있습니다. 마찬가지로, this.eventsSubject.next({data});그 부모의 this.events.subscribe(({data}) => doSomething(data));자식이다.
vince

2
구독 취소를 추가하기 위해이 훌륭한 답변을 편집했습니다. +1
Umar Farooq Khawaja

1
아마도 여기에서 초보자 질문 일 것입니다. eventsSubject주제로 구독하는 대신 Observable 로 변환 하는 이유는 무엇 입니까?
Justin Morgan

11
Observable로 이벤트 변환하기 하위 컴포넌트가 next ()를 호출하지 못하도록합니다.
BlueNC

2
이 솔루션 덕분에 IT가 작동하지만 콘솔에 오류가 발생합니다. "core.js : 6185 ERROR TypeError : Cannot read property 'subscribe'of undefined"오류가 ngOnInit의 events.subscribe ()를 가리키고 있습니다. 하위 구성 요소 : "this.eventsSubscription = this.events.subscribe (() => doSomething ());"사용중인 버전 : "@ angular / cli": "~ 9.1.0"및 "rxjs" : "~ 6.5.4"
Eduardo

72

내가 아는 한, 그렇게 할 수있는 두 가지 표준 방법이 있습니다.

1. @ 입력

부모의 데이터가 변경 될 때마다 자식은 ngOnChanges 메서드에서 이에 대한 알림을받습니다. 아이는 그것에 대해 행동 할 수 있습니다. 이것은 아이와 상호 작용하는 표준 방법입니다.

Parent-Component
public inputToChild: Object;

Parent-HTML
<child [data]="inputToChild"> </child>       

Child-Component: @Input() data;

ngOnChanges(changes: { [property: string]: SimpleChange }){
   // Extract changes to the input property by its name
   let change: SimpleChange = changes['data']; 
// Whenever the data in the parent changes, this method gets triggered. You 
// can act on the changes here. You will have both the previous value and the 
// current value here.
}
  1. 공유 서비스 개념

서비스를 만들고 공유 서비스에서 Observable을 사용합니다. 자녀가이를 구독하고 변경 사항이있을 때마다 자녀에게 알림이 전송됩니다. 이것은 또한 널리 사용되는 방법입니다. 입력으로 전달한 데이터 이외의 것을 보내려는 경우이를 사용할 수 있습니다.

SharedService
subject: Subject<Object>;

Parent-Component
constructor(sharedService: SharedService)
this.sharedService.subject.next(data);

Child-Component
constructor(sharedService: SharedService)
this.sharedService.subject.subscribe((data)=>{

// Whenever the parent emits using the next method, you can receive the data 
in here and act on it.})

나는 첫 번째 방법을 시도했고 어느 시점까지 잘 작동했고 그 후에 값이 지금 변경되었습니다. 이것 외에는 더 이상의 설명이 없었습니다.
code1

2
ExpressionChangedAfterItHasBeenCheckedError를 의미하는 경우이 오류는 프로덕션 모드에서 발생하지 않습니다.
user1337

<child [data]="inputToChild"> </child>아마도 <child [data]="(inputToChild)"> </child>변경을 받아야합니다
pmc

28

부모 구성 요소에서 @ViewChild ()를 사용하여 자식 구성 요소의 메서드 / 변수에 액세스 할 수 있습니다.

@Component({
  selector: 'app-number-parent',
  templateUrl: './number-parent.component.html'
})
export class NumberParentComponent {
    @ViewChild(NumberComponent)
    private numberComponent: NumberComponent;
    increase() {
       this.numberComponent.increaseByOne();
    }
    decrease() {
       this.numberComponent.decreaseByOne();
    }
} 

최신 정보:

Angular 8 이상-

@ViewChild(NumberComponent, { static: false })

4
이것은 Observable로 작업하는 것보다 깨끗해 보입니다. 단점은 아이가 시야에 있어야한다는 것입니다. 예를 들어 하위 항목이 라우팅과 함께로드되면 이처럼 실패 numberComponent합니다 undefined.
Shy Agam

1
이것이 좋은 습관입니까? 나는 관찰 가능한 것보다 더 깨끗한 사실에 동의하지만 부모로부터 자식의 변수를 조작하는 것에 대해 의구심을 가지고 있습니다. 어쨌든, 그것은 내 필요에 아주 잘 작동했습니다. 감사합니다!
Takatalvi

1
이것은 좋은 팁입니다. @ViewChild가 Angular 8에서 변경되었거나 적어도 ViewChild의 옵션을 지정해야하는 것 같습니다. 제 경우에는 이것을 사용했습니다 : @ViewChild (Other, {static : false}) private otherComponent : Other;
Tore Aurstad

8

부모가이 입력에 바인딩 할 수 있도록 자식 구성 요소에서 @Input () 데코레이터를 사용합니다.

자식 구성 요소에서 그대로 선언합니다.

@Input() myInputName: myType

부모에서 자식으로 속성을 바인딩하려면 바인딩 괄호와 그 사이에 입력 이름을 템플릿에 추가해야합니다.

예 :

<my-child-component [myChildInputName]="myParentVar"></my-child-component>

그러나 객체는 참조로 전달되므로 객체가 자식에서 업데이트되면 부모의 var가 너무 업데이트됩니다. 이로 인해 언젠가 원치 않는 동작이 발생할 수 있습니다. 기본 유형을 사용하면 값이 복사됩니다.

더 읽어 보려면 :

문서 : https://angular.io/docs/ts/latest/cookbook/component-communication.html


1

부모 내에서 @ViewChild를 사용하여 자식을 참조 할 수 있습니다. 필요한 경우 (즉, 이벤트가 시작될 때) @ViewChild 참조를 사용하여 부모의 자식에서 메서드를 실행할 수 있습니다.

당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.