Gọi phương thức thành phần con từ lớp cha - Angular


130

Tôi đã tạo một thành phần con có một phương thức mà tôi muốn gọi.

Khi tôi gọi phương thức này, nó chỉ kích hoạt console.log()dòng, nó sẽ không thiết lập thuộc testtính ??

Dưới đây là ứng dụng Angular khởi động nhanh với các thay đổi của tôi.

Cha mẹ

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

Đứa trẻ

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

Tôi cũng có thể đặt thuộc testtính như thế nào?



Bạn có thể kiểm tra câu trả lời này tại đây: stackoverflow.com/a/53057589/6663458
Muhammad Mabrouk

Câu trả lời:


210

Bạn có thể làm điều này bằng cách sử dụng @ViewChildđể biết thêm thông tin, hãy kiểm tra liên kết này

Với bộ chọn loại

thành phần con

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

thành phần mẹ

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

  @ViewChild(ChildCmp) child:ChildCmp;

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

Với bộ chọn chuỗi

thành phần con

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

thành phần mẹ

@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
Tôi đã làm theo cách tiếp cận của bạn nhưng gặp lỗi khi sử dụng chỉ thị: [ChildCmp], Lỗi cho biết: chỉ thị 'không tồn tại trong loại' Thành phần '. Tôi đã googled nó và nhận thấy các lệnh không được chấp nhận trong rc5. Vậy làm thế nào để xử lý nó trên phiên bản mới hơn. Xin vui lòng giúp đỡ.
Waleed Shahzaib

1
hãy thử liên kết này angle.io/guide/component-interaction và nhận xét liên kết chỉ thị
rabfmnb

5
Làm thế nào để làm cho nó hoạt động khi có nhiều trẻ em cùng một lớp ??
Anandhu Ajayakumar

@rashfmnb "Dự kiến ​​khai báo". Một lỗi sắp xảy ra khi tôi cố gắng viết @ViewChild ('child') con: ChildCmp; trong thành phần. Xin vui lòng giúp đỡ! Và tôi cũng không thể nhập cùng một chỉ thị, nó cho tôi lỗi như "chỉ thị: (typeof EmployeeProfileC ..." không thể gán cho tham số kiểu 'Thành phần'. Đối tượng đen chỉ có thể chỉ định các thuộc tính đã biết, còn 'chỉ thị' thì không tồn tại ở loại 'Thành phần'. "
Trilok Pathak.

1
Đây là một câu trả lời đúng, nhưng nó tạo ra các thành phần liên kết chặt chẽ . Một mô hình tốt hơn là sử dụng Inputcác thuộc tính: một thuộc tính có thể quan sát được mà đứa trẻ phản ứng bằng cách gọi hàm bên trong của chính nó . Xem câu trả lời của người dùng6779899
Bogdan D

56

Điều này làm việc cho tôi! Đối với Angular 2, gọi phương thức thành phần con trong thành phần mẹ

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 trong dòng này là gì: @ViewChild (ChildComponent) con: ChildVM;
Waleed Shahzaib

@WaleedShahzaib Tôi nghĩ ý ChildComponentcủa OPChildVM
Ajeet Shah,

1
Tôi nghĩ rằng điều này sẽ tạo ra một thể hiện riêng biệt của thành phần nhưng nó thực sự gọi hàm từ thể hiện của bạn với các biến của nó ở trạng thái hiện tại của thành phần đó, thánh thần! phương pháp này là cách tốt hơn câu trả lời đầu tiên!
tatsu

3
Tôi luôn nhận được giá trị Không xác định của "this.child"
Ambuj Khanna

2
Dự đoán của tôi cho việc 'this.child' không được xác định là ViewChild đang trỏ vào một cái gì đó không tồn tại trong mẫu hoặc bạn đang cố gắng truy cập nó quá sớm trong vòng đời, ví dụ như trong hàm tạo.
tony

34

Tôi nghĩ cách dễ dàng nhất là sử dụng Chủ đề. Trong mã ví dụ dưới đây, đứa trẻ sẽ được thông báo mỗi khi 'tellChild' được gọi.

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

Làm việc mẫu trên Stackblitz


4
Đây là một giải pháp thanh lịch, tuy nhiên nó không hoạt động bình thường trong mọi trường hợp, có thể là do tính năng phát hiện thay đổi Angular không hoạt động từ đăng ký.
Alexei

1
Tìm thấy đây là giải pháp tốt nhất cho trường hợp sử dụng của tôi. Hoạt động như một sự quyến rũ. Cảm ơn!
Weston

Khéo léo ! Đối với các trường hợp đơn giản hơn, bạn có thể tránh chi phí Chủ đề / Đăng ký bằng cách chuyển một đối tượng có phương thức gọi lại cho phần tử con. Tương tự như trên, con ghi đè cuộc gọi lại để nhận chỉ thị từ cha mẹ.
shr

@shr bất kỳ cơ hội nào bạn có thể chia sẻ giải pháp của mình để vượt qua một đối tượng với callback?
Imad El Hitti

1
Đây là giải pháp thanh lịch, đây sẽ là câu trả lời được chấp nhận, chỉ cần thay đổi phương thức nhập như nhập {Chủ đề} từ 'rxjs';
VIKAS KOHLI

5

Angular - Gọi phương thức của thành phần con trong mẫu của thành phần mẹ

Bạn có ParentComponent và ChildComponent trông như thế này.

parent.component.html

nhập mô tả hình ảnh ở đây

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

Khi giao bóng, nó trông như thế này:

nhập mô tả hình ảnh ở đây

Khi người dùng tập trung vào phần tử đầu vào của ParentComponent, bạn muốn gọi phương thức doSomething () của ChildComponent.

Đơn giản chỉ cần làm điều này:

  1. Cung cấp cho bộ chọn app-con trong parent.component.html một tên biến DOM (tiền tố bằng # - hashtag) , trong trường hợp này chúng tôi gọi nó là appChild.
  2. Gán giá trị biểu thức (của phương thức bạn muốn gọi) cho sự kiện trọng tâm của phần tử đầu vào.

nhập mô tả hình ảnh ở đây

Kết quả:

nhập mô tả hình ảnh ở đây


OK, nhưng chúng tôi cũng muốn làm điều đó theo chương trình sử dụng ts
canbax

Để sử dụng từ bên trong thành phần: @ViewChild('appChild', { static: false }) appChild: ElementRef<HTMLElement>;và sử dụng sau nàythis.appChild.doSomething()
Gil Epshtain

4

Câu trả lời của user6779899 là gọn gàng và chung chung hơn Tuy nhiên, dựa trên yêu cầu của Imad El Hitti, một giải pháp trọng lượng nhẹ được đề xuất ở đây. Điều này có thể được sử dụng khi một thành phần con chỉ được kết nối chặt chẽ với một thành phần gốc.

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

Hãy xem xét ví dụ sau,

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

Đọc thêm về @ViewChild tại đây.


0

Tôi đã gặp tình huống chính xác trong đó Thành phần gốc có một Selectphần tử trong một biểu mẫu và khi gửi, tôi cần gọi phương thức của Thành phần con có liên quan theo giá trị đã chọn từ phần tử được chọn.

Parent.HTML:

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

Phụ huynh.TS:

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

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

Hi vọng điêu nay co ich.

Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.