자식은 Angular 2에서 부모 이벤트를 수신합니다.


82

Angular 문서에는 부모의 자식 이벤트 수신에 대한 주제가 있습니다. 괜찮아. 하지만 내 목적은 반대입니다!. 내 앱에는 관리자 페이지의 레이아웃보기 (사이드 바 메뉴, 작업 표시 줄, 상태 등)를 보유하는 'admin.component'가 있습니다. 이 상위 구성 요소에서는 관리자의 다른 페이지간에 기본보기를 변경하기 위해 라우터 시스템을 구성했습니다. 문제는 변경 후 항목을 저장하고 사용자가 작업 표시 줄 (admin.component에 배치됨)에서 저장 버튼을 클릭하고 하위 구성 요소는 직원 저장을 위해 해당 클릭 이벤트를 수신해야한다는 것입니다.


2
이를 수행하는 가장 좋은 방법은 서비스를 사용하고 이벤트를 전달하는 관찰 가능 항목을 사용하는 것 같습니다.
zpul 2016-06-07

귀하의 질문이 하나에서 너무 비슷되지 않습니다 : stackoverflow.com/questions/35560860/...
freethebees

@freethebees 아마도 해결책은 같지만 문제의 형태는 다르며 제 의도는이 상황에 대한 최선의 접근 방식을 찾는 것입니다.
하메드 Hamedi

하위 구성 요소에 전달되는 단일 이벤트에 대한 서비스를 설정하지 않을 것입니다.
TR3B

답변:


101

이 문서가 도움이 될 것이라고 생각합니다.

사실 부모가 자식에게 제공하는 관찰 가능 / 주제를 활용할 수 있습니다. 그런 것 :

@Component({
  (...)
  template: `
    <child [parentSubject]="parentSubject"></child>
  `,
  directives: [ ChildComponent ]
})
export class ParentComponent {
  parentSubject:Subject<any> = new Subject();

  notifyChildren() {
    this.parentSubject.next('some value');
  }
}

하위 구성 요소는이 주제를 간단히 구독 할 수 있습니다.

@Component({
  (...)
})
export class ChildComponent {
  @Input()
  parentSubject:Subject<any>;

  ngOnInit() {
    this.parentSubject.subscribe(event => {
      // called when the notifyChildren method is
      // called in the parent component
    });
  }

  ngOnDestroy() {
    // needed if child gets re-created (eg on some model changes)
    // note that subsequent subscriptions on the same subject will fail
    // so the parent has to re-create parentSubject on changes
    this.parentSubject.unsubscribe();
  }

}

그렇지 않으면 유사한 방식으로 이러한 주제를 포함하는 공유 서비스를 활용할 수 있습니다.


내 자식 구성 요소의 콜백은 부모 구성 요소가 ngInit 내에서 다음 값을 브로드 캐스트하지 않는 한 실행되지 않습니다. 그 이유는 무엇입니까?
cjsimon apr

5
ViewChild보다이 방법을 사용하면 어떤 이점이 있습니까?
sunnyiitkgp

좀 더 전문적으로 보이지만 내 상황에서 몇 시간 동안 실험 해 본 후 하위 요소를 추가 / 제거 할 때 (따라서 주제에서 구독 취소) UnsubscribeErrors 문제에서 벗어날 수 없었습니다. 그래서 TimeBoxing을 통해 @StephenPaul의 훨씬 더 직접적인 답변을 얻었습니다. 어쨌든 대답에 감사 드리며 아마도 rxjs 라이브러리를 완전히 이해하고 완벽하게 작동하도록 예제를 올바르게 (추가) 조정하기에 충분하지 않을 것입니다.
Bernoulli IT

116

후손을 위해 좀 더 일반적인 해결책을 언급하겠다고 생각 했습니다. ViewChild에 대한 참조를 얻은 다음 해당 메서드 중 하나를 직접 호출하기 만하면됩니다.

@Component({
  selector: 'app-child'
})
export class ChildComponent {

  notifyMe() {
    console.log('Event Fired');
  }
}

@Component({
  selector: 'app-parent',
  template: `<app-child #child></app-child>`
})
export class ParentComponent {

  @ViewChild('child')
  private child: ChildComponent;

  ngOnInit() {
    this.child.notifyMe();
  }
}

3
그것은 바로 내가 부모 구성 요소를 입력 할 때 충돌 ... Cannot read property 'notifyMe' of undefined.
친절한 사용자

1
@ThierryTemplier의 좀 더 전문적인 느낌의 솔루션과 비교 하여이 매우 격렬한 솔루션을 찾았습니다 (제 의견 참조).
Bernoulli IT

2
@BernoulliIT 당신은 좋은 지적을합니다. 나는 하루가 끝나면 거의 같은 일을 성취한다고 생각합니다. 내 솔루션은 더 적은 코드를 사용합니다. 그의 솔루션은 부모 구성 요소가 메시지를 보내기 위해 자식 구성 요소를 주입 할 필요가 없음을 의미합니다. RXJS는 훌륭하지만 Angular 프로젝트에서 과도하게 사용되는 경우가 많습니다. 사람들은이 '실버 총알'이나 뭔가를 생각합니다. 실제로 필요한 것보다 훨씬 더 복잡하게 만들 수 있습니다. 그의 ngOnDestroy()방법 안에서 그의 코멘트를보십시오 . 제가 생각하는 한 그것은 너무 모호합니다. IMHO가 발생하기를 기다리는 버그입니다.
Stephen Paul

1
"그의 ngOnDestroy () 메서드 내부에있는 그의 주석을보십시오." 그 접근 방식을 시도 할 때 그게 바로 제가 "고통 스러웠던"것이라고 생각합니다. 그 다음에는 막혔고 더 이상 조사 할 시간이 없었습니다 (제가 작업하는 상업 프로젝트의 경우). 그것은 " '내 전문 마음을 조금 hurted 만)
베르누이 IT

1
@StephenPaul에게 감사합니다. 부모님이 Viewchild 메서드를 호출하는 것은 좋았지 만 귀하의 답변은 저의 운명에 도달하는 데 도움이되었습니다!
MKJ

14

질문을 올바르게 이해하면 더 많은 뼈대 접근이 가능할 수 있습니다. 가정-

  • OP에는 상위 구성 요소에 저장 버튼이 있습니다.
  • 저장해야하는 데이터는 하위 구성 요소에 있습니다.
  • 하위 구성 요소에 필요할 수있는 다른 모든 데이터는 서비스에서 액세스 할 수 있습니다.

부모 구성 요소에서

<button type="button" (click)="prop1=!prop1">Save Button</button>
<app-child-component [setProp]='prop1'></app-child-component>

그리고 아이 ..

prop1:boolean;
  @Input()
  set setProp(p: boolean) {
    // -- perform save function here
}

이것은 단순히 버튼 클릭을 하위 구성 요소로 보냅니다. 거기에서 하위 구성 요소는 데이터를 독립적으로 저장할 수 있습니다.

편집 : 부모 템플릿의 데이터도 버튼 클릭과 함께 전달되어야하는 경우이 방법으로도 가능합니다. 이 경우 알려 주시면 코드 샘플을 업데이트하겠습니다.


0

받는 사람들을 위해 Cannot read property 'notifyMe' of undefined

ngAfterViewInit()intead 내부의 메소드를 호출하십시오.ngOnInit()

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