親クラスから子コンポーネントメソッドを呼び出す-Angular


130

呼び出したいメソッドを持つ子コンポーネントを作成しました。

このメソッドを呼び出すと、console.log()行が起動されるだけで、testプロパティは設定されませんか?

以下は、変更を加えたAngularアプリのクイックスタートです。

import { Component } from '@angular/core';
import { NotifyComponent }  from './notify.component';

@Component({
    selector: 'my-app',
    template:
    `
    <button (click)="submit()">Call Child Component Method</button>
    `
})
export class AppComponent {
    private notify: NotifyComponent;

    constructor() { 
      this.notify = new NotifyComponent();
    }

    submit(): void {
        // execute child component method
        notify.callMethod();
    }
}

import { Component, OnInit } from '@angular/core';

@Component({
    selector: 'notify',
    template: '<h3>Notify {{test}}</h3>'
})
export class NotifyComponent implements OnInit {
   test:string; 
   constructor() { }

    ngOnInit() { }

    callMethod(): void {
        console.log('successfully executed.');
        this.test = 'Me';
    }
}

testプロパティをどのように設定できますか?



この回答はこちらで確認できます:stackoverflow.com/a/53057589/6663458
Muhammad Mabrouk

回答:


209

あなたは使用してこれを行うことができます@ViewChildより多くの情報のチェックのために、このリンクを

タイプセレクター付き

子コンポーネント

@Component({
  selector: 'child-cmp',
  template: '<p>child</p>'
})
class ChildCmp {
  doSomething() {}
}

親コンポーネント

@Component({
  selector: 'some-cmp',
  template: '<child-cmp></child-cmp>',
  directives: [ChildCmp]
})
class SomeCmp {

  @ViewChild(ChildCmp) child:ChildCmp;

  ngAfterViewInit() {
    // child is set
    this.child.doSomething();
  }
}

文字列セレクター付き

子コンポーネント

@Component({
  selector: 'child-cmp',
  template: '<p>child</p>'
})
class ChildCmp {
  doSomething() {}
}

親コンポーネント

@Component({
  selector: 'some-cmp',
  template: '<child-cmp #child></child-cmp>',
  directives: [ChildCmp]
})
class SomeCmp {

  @ViewChild('child') child:ChildCmp;

  ngAfterViewInit() {
    // child is set
    this.child.doSomething();
  }
}

6
私はあなたのアプローチに従いましたが、ディレクティブの使用中にエラーが発生しました:[ChildCmp]、エラーは言う:タイプ「コンポーネント」にディレクティブは存在しません。私はそれをグーグルで調べて、ディレクティブがrc5で廃止されているのを見つけました。新しいバージョンでそれを処理する方法。助けてください。
Waleed Shahzaib 2017

1
このリンクangular.io/guide/component-interactionを試して、ディレクティブリンクにコメントしてください
rashfmnb '29

5
同じクラスの子が複数いる場合にそれを機能させるには?
Anandhu Ajayakumar

@rashfmnb "宣言が必要です"。@ViewChild( 'child')child:ChildCmp;をコンポーネントに書き込もうとすると、エラーが発生します。助けてください!また、ディレクティブに同じものをインポートできないため、「directive:(typeof EmployeeProfileC ...」はタイプ「Component」のパラメーターに割り当てることができません。オブジェクトリテラルは既知のプロパティのみを指定でき、「directive」はそうではありません。タイプ「コンポーネント」に存在します。 "
Trilok Pathak '29

1
これは正解ですが、密結合コンポーネントを生成します。より良いパターンは、Inputプロパティを使用することです:子が自身の内部関数を呼び出すことによって反応するオブザーバブル。user6779899の回答を見る
Bogdan D

56

これは私のために働いた!Angular 2の場合、親コンポーネントで子コンポーネントメソッドを呼び出す

Parent.component.ts

    import { Component, OnInit, ViewChild } from '@angular/core';
    import { ChildComponent } from '../child/child'; 
    @Component({ 
               selector: 'parent-app', 
               template: `<child-cmp></child-cmp>` 
              }) 
    export class parentComponent implements OnInit{ 
        @ViewChild(ChildComponent ) child: ChildComponent ; 

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

Child.component.ts

import { Component } from '@angular/core';
@Component({ 
  selector: 'child-cmp', 
  template: `<h2> Show Child Component</h2><br/><p> {{test }}</p> ` 
})
export class ChildComponent {
  test: string;
  ChildTestCmp() 
  { 
    this.test = "I am child component!"; 
  }
 }


4
この行のChildVMとは:@ViewChild(ChildComponent)child:ChildVM;
Waleed Shahzaib 2017年

@WaleedShahzaib OPが意味するChildComponentものだと思うChildVM
Ajeet Shah

1
これでコンポーネントの個別のインスタンスが作成されると思いましたが、実際には、コンポーネントの現在の状態にある変数であるインスタンスから関数を呼び出します。この方法は最初の答えよりもはるかに優れています!
-tatsu

3
私は常に「this.child」の未定義の値を取得しています
Ambuj Khanna

2
「this.child」が未定義であるとの私の推測は、ViewChildがテンプレートに存在しないものを指しているか、またはコンストラクターなどのライフサイクルの早い段階でアクセスしようとしていることです。
トニー

34

最も簡単な方法は件名を使用することだと思います。以下のコード例では、「tellChild」が呼び出されるたびに子に通知されます。

Parent.component.ts

import {Subject} from 'rxjs/Subject';
...
export class ParentComp {
    changingValue: Subject<boolean> = new Subject();
    tellChild(){
    this.changingValue.next(true);
  }
}

Parent.component.html

<my-comp [changing]="changingValue"></my-comp>

Child.component.ts

...
export class ChildComp implements OnInit{
@Input() changing: Subject<boolean>;
ngOnInit(){
  this.changing.subscribe(v => { 
     console.log('value is changing', v);
  });
}

Stackblitzの作業サンプル


4
これはエレガントなソリューションですが、すべてのケースで適切に機能するわけではありません。おそらく、Angular変更検出がサブスクライブから機能しないためです。
Alexei

1
これが私のユースケースに最適なソリューションであることがわかりました。魅力のように機能します。ありがとう!
Weston

きちんと!より単純なケースでは、コールバックメソッドを持つオブジェクトを子に渡すことにより、Subject / Subscribeのオーバーヘッドを回避できます。上記と同様に、子は親から指示を受け取るためにコールバックをオーバーライドします。
shr

@shrコールバックでオブジェクトを渡すためのソリューションを共有できる可能性はありますか?
Imad El Hitti

1
これはエレガントなソリューションです。これは受け入れられる答えであるはずです。'rxjs 'からimport {Subject}のようなインポート方法を変更するだけです。
VIKAS KOHLI

5

Angular –親コンポーネントのテンプレートで子コンポーネントのメソッドを呼び出す

次のようなParentComponentとChildComponentがあります。

parent.component.html

ここに画像の説明を入力してください

parent.component.ts

import {Component} from '@angular/core';

@Component({
  selector: 'app-parent',
  templateUrl: './parent.component.html',
  styleUrls: ['./parent.component.css']
})
export class ParentComponent {
  constructor() {
  }
}

child.component.html

<p>
  This is child
</p>

child.component.ts

import {Component} from '@angular/core';

@Component({
  selector: 'app-child',
  templateUrl: './child.component.html',
  styleUrls: ['./child.component.css']
})
export class ChildComponent {
  constructor() {
  }

  doSomething() {
    console.log('do something');
  }
}

サーブすると、次のようになります。

ここに画像の説明を入力してください

ユーザーがParentComponentのinput要素にフォーカスしたとき、ChildComponentのdoSomething()メソッドを呼び出します。

単にこれを行う:

  1. parent.component.htmlのapp-childセレクターにDOM変数名を付ける (接頭辞#-ハッシュタグ)を付けます。この場合は、appChildと呼びます。
  2. (呼び出すメソッドの)式の値を入力要素のfocusイベントに割り当てます。

ここに画像の説明を入力してください

結果:

ここに画像の説明を入力してください


OKですが、tsを使用してプログラムで実行することもできます
canbax

コンポーネント内から使用:@ViewChild('appChild', { static: false }) appChild: ElementRef<HTMLElement>;後で使用this.appChild.doSomething()
Gil Epshtain

4

user6779899の答えは、きちんとして一般的です。しかし、Imad El Hittiの要求に基づいて、ここでは軽量のソリューションを提案します。これは、子コンポーネントが1つの親にのみ密接に接続されている場合に使用できます。

Parent.component.ts

export class Notifier {
    valueChanged: (data: number) => void = (d: number) => { };
}

export class Parent {
    notifyObj = new Notifier();
    tellChild(newValue: number) {
        this.notifyObj.valueChanged(newValue); // inform child
    }
}

Parent.component.html

<my-child-comp [notify]="notifyObj"></my-child-comp>

Child.component.ts

export class ChildComp implements OnInit{
    @Input() notify = new Notifier(); // create object to satisfy typescript
    ngOnInit(){
      this.notify.valueChanged = (d: number) => {
            console.log(`Parent has notified changes to ${d}`);
            // do something with the new value 
        };
    }
 }

2

次の例を考えてみましょう。

    import import { AfterViewInit, ViewChild } from '@angular/core';
    import { Component } from '@angular/core';
    import { CountdownTimerComponent }  from './countdown-timer.component';
    @Component({
        selector: 'app-countdown-parent-vc',
        templateUrl: 'app-countdown-parent-vc.html',
        styleUrl: [app-countdown-parent-vc.css]
    export class CreateCategoryComponent implements OnInit {
         @ViewChild(CountdownTimerComponent, {static: false})
         private timerComponent: CountdownTimerComponent;
         ngAfterViewInit() {
             this.timerComponent.startTimer();
         }

         submitNewCategory(){
            this.ngAfterViewInit();     
         }

@ViewChildの詳細については、こちらをご覧ください。


0

私は親コンポーネントが持っている正確な状況がありました Selectフォームに要素送信時に、select要素から選択された値に従って、関連するChild-Componentのメソッドを呼び出す必要がありました。

Parent.HTML:

<form (ngSubmit)='selX' [formGroup]="xSelForm">
    <select formControlName="xSelector">
      ...
    </select>
<button type="submit">Submit</button>
</form>
<child [selectedX]="selectedX"></child>

Parent.TS:

selX(){
  this.selectedX = this.xSelForm.value['xSelector'];
}

Child.TS:

export class ChildComponent implements OnChanges {
  @Input() public selectedX;

  //ngOnChanges will execute if there is a change in the value of selectedX which has been passed to child as an @Input.

  ngOnChanges(changes: { [propKey: string]: SimpleChange }) {
    this.childFunction();
  }
  childFunction(){ }
}

お役に立てれば。

弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.