typescript 从父类调用子组件方法- Angular

qij5mzcb  于 7个月前  发布在  TypeScript
关注(0)|答案(9)|浏览(113)

我已经创建了一个子组件,它有一个我想调用的方法。
当我调用这个方法时,它只触发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属性?

carvr3hs

carvr3hs1#

您可以通过使用@ViewChild来完成此操作。更多信息请查看此link

带类型选择器

辅元件

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

368yc8dk

368yc8dk2#

我认为最简单的方法是使用Subject。在下面的示例代码中,每次调用'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上的工作样本

yfwxisqw

yfwxisqw3#

这对我很有用!对于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!"; 
  }
 }

k5ifujac

k5ifujac4#

Angular -在父组件的模板中调用子组件的方法
你有ParentComponent和ChildComponent,看起来像这样。
parent.component.html
x1c 0d1x的数据
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变量名**(前缀为# - hashtag)**,在本例中我们称之为appChild。
1.为输入元素的焦点事件分配表达式值(您要调用的方法的值)。



结果:


txu3uszq

txu3uszq5#

parent.component.html

<app-child #childComponent></app-child>

字符串
parent.component.ts

@Component({
    selector: 'app-parent',
    templateUrl: './app-parent.component.html',
    styleUrls: ['./app-parent.component.scss']
})
export class ParentComponent {
    @ViewChild('childComponent', {static: false}) childComponent: ChildComponent;

    anyMethod(): void {
        childComponent.updateData() // updateData is a child method
    }
}


child.component.ts

@Component({
    selector: 'app-child',
    templateUrl: './app-child.component.html',
    styleUrls: ['./app-child.component.scss']
})
export class ChildComponent {
    updateData(): void {
      // Method code goes here
    }
}

ql3eal8s

ql3eal8s6#

user6779899的答案是简洁和更通用的。然而,根据Imad El Hitti的要求,这里提出了一个轻量级的解决方案。这可以在子组件仅与一个父组件紧密连接时使用。

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

aamkag61

aamkag617#

考虑以下示例,

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, AfterViewInit {
    @ViewChild(CountdownTimerComponent, {static: false}) private timerComponent: CountdownTimerComponent;
    ngAfterViewInit() {
        this.timerComponent.startTimer();
    }

    submitNewCategory(){
        this.ngAfterViewInit();
    }
}

字符串
阅读更多关于@ViewChild这里.

9o685dep

9o685dep8#

我有一个确切的情况,父组件在表单中有一个Select元素,在提交时,我需要根据从选择元素中选择的值调用相关的子组件的方法。

父级.HTML:

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

字符串

父TS:

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

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


希望这对你有帮助。

zphenhs4

zphenhs49#

我用EventEmitter来做这个。

parent.component.ts

@Component({
  selector: "app-parent",
  template: '<app-child listener="notify"></app-child>' +
            '<button (click)="notify.emit()">Call child function</button>',
  //...
})
export class ParentComponent {
  notify: EventEmitter<void> = new EventEmitter<void>()
}

字符串

child.component.ts

@Component({
  selector: "app-child",
  template: "<i>Child component text</i>",
  //...
})
export class ChildComponent {
  #listener: EventEmitter<void> = new EventEmitter<void>()
  @Input()
  set listener(emitter: EventEmitter<void>) {
    this.#listener.unsubscribe()
    this.#listener = emitter
    this.#listener.subscribe(this.childFunction.bind(this))
  }

  childFunction() {
    console.log("Child function called")
  }
}


这种方法的优点:

  • reliable -即使您稍后在代码中更改EventEmitterParentComponent中的notify属性值),也可以正常工作
  • 保持组件解耦

坏的部分:

  • 与其他解决方案相比,

如果需要传递一些数据,请将void(在EventEmitter<void>中)替换为所需的类型。
如果你需要传递一个以上的参数,那么我建议创建interface,并将数据作为一个对象传递,其中包含你需要传递给ChildComponent的所有参数。更快(也更脏)的解决方案是将类型设置为any,并传递你想要的任何对象。

传入对象作为参数的示例

parent.component.ts

@Component({
  selector: "app-parent",
  template: '<app-child listener="notify"></app-child>' +
            '<button (click)="callChild()">Call child function</button>',
  //...
})
export class ParentComponent {
  notify: EventEmitter<any> = new EventEmitter<any>()

  callChild() {
    this.notify.emit({title: 'Parent call', id: 1})
  }
}

child.component.ts

@Component({
  selector: "app-child",
  template: "<i>Child component text</i>",
  //...
})
export class ChildComponent {
  #listener: EventEmitter<any> = new EventEmitter<any>()
  @Input()
  set listener(emitter: EventEmitter<any>) {
    this.#listener.unsubscribe()
    this.#listener = emitter
    this.#listener.subscribe(this.childFunction.bind(this))
  }

  childFunction(data: any) {
    console.log("Child function called")
    console.log(data)
  }
}

相关问题