Üst sınıftan alt bileşen yöntemini çağır - Angular


130

Çağırmak istediğim bir yönteme sahip bir alt bileşen oluşturdum.

Bu yöntemi çağırdığımda, yalnızca console.log()satırı ateşler , testözelliği ayarlamaz ??

Aşağıda değişikliklerimle hızlı başlangıç ​​Angular uygulaması var.

ebeveyn

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

Çocuk

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Özelliği de nasıl ayarlayabilirim ?



Bu yanıtı buradan kontrol edebilirsiniz: stackoverflow.com/a/53057589/6663458
Muhammad Mabrouk

Yanıtlar:


210

Daha @ViewChildfazla bilgi için bu bağlantıyı kontrol ederek bunu yapabilirsiniz

Tip seçici ile

alt bileşen

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

üst bileşen

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

  @ViewChild(ChildCmp) child:ChildCmp;

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

Dize seçici ile

alt bileşen

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

üst bileşen

@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
Yaklaşımınızı izledim, ancak yönergeleri kullanırken hata alıyorum: [ChildCmp], Hata diyor ki: yönergeler 'Bileşen' türünde mevcut değil. Google'da araştırdım ve yönergelerin rc5'te kullanımdan kaldırıldığını gördüm. Peki yeni sürümde bununla nasıl başa çıkılacağı. Lütfen yardım et.
Waleed Shahzaib

1
Bu bağlantı denemek angular.io/guide/component-interaction ve direktifler bağlantı açıklama
rashfmnb

5
Aynı sınıftan birden fazla çocuk varken nasıl çalıştırılır?
Anandhu Ajayakumar

@rashfmnb "Beyan bekleniyor". @ViewChild ('child') child: ChildCmp; bileşeninde yazmaya çalıştığımda bir hata geliyor. Lütfen yardım et! Ayrıca yönergede aynısını içe aktaramıyorum, bana "yönerge: (typeof EmployeeProfileC ..." gibi bir hata veriyor 'Bileşen' türündeki parametrelere atanamaz. Nesne değişmezi yalnızca bilinen özellikleri belirtebilir ve 'yönerge' bunu yapmaz 'Bileşen' türünde var. "
Trilok Pathak

1
Bu doğru bir cevap, ancak sıkı bir şekilde bağlı bileşenler üretir . Daha iyi bir model, Inputözellikleri kullanmaktır : Çocuğun kendi dahili işlevini çağırarak tepki verdiği gözlemlenebilir . User6779899 'nin cevabını görün
Bogdan D

56

Bu benim için çalıştı! Angular 2 için, üst bileşendeki alt bileşen yöntemini çağır

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
Bu satırdaki ChildVM nedir: @ViewChild (ChildComponent) child: ChildVM;
Waleed Shahzaib

@WaleedShahzaib Kastettiğim OP düşünüyorum ChildComponenttarafındanChildVM
Ajeet Şah

1
Bunun bileşenin ayrı bir örneğini oluşturacağını düşünmüştüm ama aslında sizin örneğinizdeki işlevi, o bileşenin mevcut durumundaki değişkenleriyle birlikte çağırıyor, kutsal inek! bu yöntem ilk cevaptan çok daha iyi!
tatsu

3
"This.child" in Tanımsız değerini her zaman alıyorum
Khanna

2
Benim tahminim 'this.child' tanımsız olarak ya ViewChild şablonda olmayan bir şeye işaret ediyor ya da yaşam döngüsünde çok erken erişmeye çalışıyorsunuz, örneğin yapıcıda.
tony

34

Bence en kolay yol Konu kullanmak. Aşağıdaki örnek kodda, çocuk 'tellChild' her çağrıldığında bilgilendirilecektir.

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 üzerinde çalışma örneği


4
Bu zarif bir çözümdür, ancak her durumda düzgün çalışmaz, muhtemelen açısal değişiklik algılamasının abone tarafından çalışmaması nedeniyle.
Alexei

1
Bunu kullanım durumum için en iyi çözüm olarak buldum. Tıkır tıkır çalışıyor. Teşekkürler!
Weston

Düzgün! Daha basit durumlar için, geri arama yöntemi olan bir nesneyi çocuğa ileterek Konu / Abone olma ek yükünü önleyebilirsiniz. Yukarıdakine benzer şekilde, çocuk ebeveynden göstergeler almak için geri aramayı geçersiz kılar.
shr

@shr geri arama ile bir nesneyi iletmek için çözümünüzü paylaşma şansınız var mı?
Imad El Hitti

1
Bu mükemmel bir çözüm, bu kabul edilen cevap olmalı, sadece içe aktarma yöntemini, 'rxjs'den içe aktarım {Konu}' gibi değiştirin;
VIKAS KOHLI

5

Angular - Üst Bileşen Şablonunda Alt Bileşen Yöntemini Çağırın

Şuna benzeyen ParentComponent ve ChildComponent'e sahipsiniz.

parent.component.html

görüntü açıklamasını buraya girin

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

Servis yaparken şöyle görünür:

görüntü açıklamasını buraya girin

Kullanıcı, ParentComponent'ın girdi öğesine odaklandığında, ChildComponent'ın doSomething () yöntemini çağırmak istersiniz.

Basitçe şunu yapın:

  1. Parent.component.html'de app-child selector'a bir DOM değişkeni adı verin (# - hashtag ile önek) , bu durumda biz buna appChild diyoruz.
  2. Girdi öğesinin odak olayına ifade değerini (aramak istediğiniz yöntemin) atayın.

görüntü açıklamasını buraya girin

Sonuç:

görüntü açıklamasını buraya girin


Tamam ama ts kullanarak programlı olarak da yapmak istiyoruz
canbax

Bileşenin içinden kullanım için: @ViewChild('appChild', { static: false }) appChild: ElementRef<HTMLElement>;ve daha sonra kullanımthis.appChild.doSomething()
Gil Epshtain

4

user6779899'un cevabı temiz ve daha geneldir. Bununla birlikte, Imad El Hitti'nin talebine göre burada hafif bir çözüm önerilmektedir. Bu, bir alt bileşen yalnızca bir ebeveyne sıkıca bağlı olduğunda kullanılabilir.

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

Aşağıdaki örneği düşünün,

    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 hakkında daha fazla bilgiyi buradan okuyun .


0

Üst bileşenin Selectbir formda bir öğeye sahip olduğu kesin bir durum yaşadım ve gönderirken, ilgili Alt Bileşenin yöntemini seçilen öğeden seçilen değere göre çağırmam gerekti.

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

Bu yardımcı olur umarım.

Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.