Panggil metode komponen anak dari kelas induk - Angular

130

Saya telah membuat komponen anak yang memiliki metode yang ingin saya panggil.

Ketika saya memanggil metode ini, itu hanya mengaktifkan console.log()baris, itu tidak akan mengatur testproperti ??

Di bawah ini adalah aplikasi Angular mulai cepat dengan perubahan saya.

Induk

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

Anak

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

Bagaimana cara mengatur testproperti juga?

shammelburg.dll
sumber
Kemungkinan duplikat Panggil metode komponen anak
Damjan Pavlica
Anda dapat memeriksa jawaban ini di sini: stackoverflow.com/a/53057589/6663458
Muhammad Mabrouk

Jawaban:

210

Anda dapat melakukan ini dengan menggunakan @ViewChilduntuk info lebih lanjut, periksa tautan ini

Dengan pemilih tipe

komponen anak

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

komponen induk

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

  @ViewChild(ChildCmp) child:ChildCmp;

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

Dengan pemilih string

komponen anak

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

komponen induk

@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();
  }
}
rashfmnb.dll
sumber
6
Saya mengikuti pendekatan Anda, tetapi saya mendapatkan kesalahan saat menggunakan arahan: [ChildCmp], Kesalahannya mengatakan: arahan 'tidak ada dalam tipe' Komponen '. Saya telah mencarinya di Google dan menemukan arahan sudah tidak digunakan lagi di rc5. Jadi bagaimana menanganinya di versi yang lebih baru. Tolong bantu.
Waleed Shahzaib
1
coba tautan ini angular.io/guide/component-interaction dan komentari tautan arahan
rashfmnb
5
Bagaimana cara membuatnya bekerja ketika ada banyak anak dari kelas yang sama ??
Anandhu Ajayakumar
@hadir_hadir Sebuah kesalahan datang ketika saya mencoba untuk menulis @ViewChild ('child') child: ChildCmp; di dalam komponen. Tolong bantu! Dan juga saya tidak dapat mengimpor yang sama dalam direktif itu memberi saya kesalahan seperti "direktif: (typeof EmployeeProfileC ... 'tidak dapat ditetapkan ke parameter jenis' Komponen '. Literal objek hanya dapat menentukan properti yang diketahui, dan' direktif 'tidak ada dalam tipe 'Komponen'. "
Trilok Pathak
1
Ini jawaban yang benar, tetapi menghasilkan komponen yang berpasangan erat . Pola yang lebih baik adalah dengan menggunakan Inputproperti: sebuah observable di mana anak bereaksi dengan memanggil fungsi internalnya sendiri . Lihat jawaban pengguna6779899
Bogdan D
56

Ini Berhasil untuk saya! Untuk Angular 2, Panggil metode komponen anak dalam komponen induk

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!"; 
  }
 }

Kaur A
sumber
4
Apa itu ChildVM di baris ini: @ViewChild (ChildComponent) child: ChildVM;
Waleed Shahzaib
@WaleedShahzaib Saya pikir OP yang dimaksud ChildComponentolehChildVM
Ajeet Shah
1
Saya pikir ini akan membuat instance terpisah dari komponen tetapi sebenarnya memanggil fungsi dari instance Anda dengan variabelnya dalam keadaan komponen saat ini, astaga! metode ini jauh lebih baik daripada jawaban pertama!
tatsu
3
Saya selalu mendapatkan nilai yang tidak ditentukan dari "this.child"
Ambuj Khanna
2
Dugaan saya untuk 'this.child' tidak ditentukan adalah bahwa ViewChild menunjuk ke sesuatu yang tidak ada di template, atau Anda mencoba mengaksesnya terlalu dini dalam siklus hidup, misalnya di konstruktor.
tony
34

Menurut saya cara paling mudah adalah menggunakan Subjek. Dalam kode contoh di bawah ini, anak akan diberi tahu setiap kali 'tellChild' dipanggil.

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

Contoh kerja di Stackblitz

pengguna6779899
sumber
4
Ini adalah solusi yang elegan, namun tidak berfungsi dengan baik dalam semua kasus, mungkin karena deteksi perubahan sudut tidak berfungsi dari langganan.
Alexei
1
Menemukan ini sebagai solusi terbaik untuk kasus penggunaan saya. Bekerja seperti pesona. Terima kasih!
Weston
Rapi! Untuk kasus yang lebih sederhana, Anda bisa menghindari overhead Subject / Subscribe dengan meneruskan objek yang memiliki metode callback ke anak. Mirip dengan yang di atas, anak mengganti callback untuk menerima indikasi dari induknya.
Shr
@shr, adakah kemungkinan Anda dapat membagikan solusi untuk meneruskan objek dengan callback?
Imad El Hitti
1
Ini adalah solusi yang elegan, ini harus menjadi jawaban yang diterima, cukup ubah metode impor seperti import {Subject} dari 'rxjs';
VIKAS KOHLI
5

Angular - Panggil Metode Komponen Anak di Templat Komponen Induk

Anda memiliki ParentComponent dan ChildComponent yang terlihat seperti ini.

parent.component.html

masukkan deskripsi gambar di sini

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

Saat disajikan, tampilannya seperti ini:

masukkan deskripsi gambar di sini

Saat pengguna fokus pada elemen masukan ParentComponent, Anda ingin memanggil metode doSomething () ChildComponent.

Cukup lakukan ini:

  1. Beri pemilih app-child di parent.component.html nama variabel DOM (awalan dengan # - hashtag) , dalam hal ini kita menyebutnya appChild.
  2. Tetapkan nilai ekspresi (metode yang ingin Anda panggil) untuk memasukkan peristiwa fokus elemen.

masukkan deskripsi gambar di sini

Hasil:

masukkan deskripsi gambar di sini

Hemant Ramphul
sumber
Oke, tapi kami juga ingin melakukannya secara terprogram menggunakan ts
canbax
Untuk digunakan dari dalam komponen: @ViewChild('appChild', { static: false }) appChild: ElementRef<HTMLElement>;dan penggunaan selanjutnyathis.appChild.doSomething()
Gil Epshtain
4

Jawaban pengguna6779899 rapi dan lebih umum Namun, berdasarkan permintaan Imad El Hitti, solusi ringan diusulkan di sini. Ini bisa digunakan ketika komponen anak terhubung erat ke satu induk saja.

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 
        };
    }
 }
Shr
sumber
2

Perhatikan contoh berikut,

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

Baca selengkapnya tentang @ViewChild di sini.

lwairore
sumber
0

Saya memiliki situasi yang tepat di mana komponen Induk memiliki file Select elemen dalam formulir dan saat mengirimkan, saya perlu memanggil metode Komponen Anak yang relevan sesuai dengan nilai yang dipilih dari elemen pilih.

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(){ }
}

Semoga ini membantu.

Vibhor Dube
sumber