从父类调用子组件方法 - Angular
Posted
技术标签:
【中文标题】从父类调用子组件方法 - Angular【英文标题】:Call child component method from parent class - Angular 【发布时间】:2016-12-22 19:52:57 【问题描述】:我创建了一个子组件,它有一个我想要调用的方法。
当我调用此方法时,它只会触发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
属性?
【问题讨论】:
Call a method of the child component的可能重复 你可以在这里查看这个答案:***.com/a/53057589/6663458 【参考方案1】:您可以通过使用@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();
【讨论】:
我遵循了您的方法,但是在使用指令时出现错误:[ChildCmp],错误说:指令'在'组件'类型中不存在。我用谷歌搜索了它,发现指令在 rc5 中已被弃用。那么如何在较新的版本上处理它。请帮忙。 试试这个链接angular.io/guide/component-interaction并评论指令链接 同班有多个孩子时如何让它工作?? @rashfmnb“预期声明”。当我尝试在组件中编写 @ViewChild('child') child:ChildCmp; 时出现错误。请帮忙!而且我也不能在指令中导入相同的内容,它给了我类似“指令:(typeof EmployeeProfileC ...”的错误不能分配给“组件”类型的参数。对象文字只能指定已知属性,而“指令”不存在于“组件”类型中。” 这是一个正确的答案,但它会产生紧密耦合的组件。更好的模式是使用Input
属性:一个可观察对象,孩子通过调用其自己的 内部函数对其做出反应。查看 user6779899 的回答【参考方案2】:
这对我有用!对于 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!";
【讨论】:
此行中的 ChildVM 是什么:@ViewChild(ChildComponent) child: ChildVM; @WaleedShahzaib 我认为 OP 的意思是ChildComponent
ChildVM
我认为这会创建一个单独的组件实例,但它实际上从您的实例调用函数,其变量处于该组件的当前状态,天哪!这个方法比第一个答案好多了!
我总是得到“this.child”的未定义值
我对 'this.child' 未定义的猜测是 ViewChild 指向模板中不存在的东西,或者您试图在生命周期中过早访问它,例如在构造函数中。【参考方案3】:
我认为最简单的方法是使用主题。在下面的示例代码中,每次调用 '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 上的工作示例
【讨论】:
这是一个优雅的解决方案,但它并非在所有情况下都能正常工作,可能是由于 Angular 更改检测无法从订阅中工作。 发现这是我用例的最佳解决方案。奇迹般有效。谢谢! 整洁!对于更简单的情况,您可以通过将具有回调方法的对象传递给子对象来避免主题/订阅开销。与上面类似,子级覆盖回调以接收来自父级的指示。 @shr 您是否有机会分享您的解决方案以通过回调传递对象? 这是一个优雅的解决方案,这应该是公认的答案,只需更改导入方法,如 import Subject from 'rxjs';【参考方案4】: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
;
【讨论】:
【参考方案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 的输入元素时,你想调用 ChildComponent 的 doSomething() 方法。
只需这样做:
-
在 parent.component.html 中给 app-child 选择器一个 DOM 变量名
(前缀为# – hashtag),在这种情况下我们称之为appChild。
将表达式值(您要调用的方法的)分配给输入元素的焦点事件。
结果:
【讨论】:
好的,但我们也想使用 ts 以编程方式完成 在组件内使用:@ViewChild('appChild', static: false ) appChild: ElementRef<HTMLElement>;
及以后使用this.appChild.doSomething()
【参考方案6】:
考虑以下示例,
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();
Read more about @ViewChild here.
【讨论】:
这是最好的答案。 无需显式调用 ngAfterViewInit()。如果在类上实现它会自动调用 需要显式调用ngAfterViewInit()
,因为我们需要显式告诉Angular调用方法startTimer()
,它在组件CountdownTimerComponent
中【参考方案7】:
我有一个确切的情况,父组件在表单中有一个Select
元素,在提交时,我需要根据从选择元素中选择的值调用相关的子组件的方法。
父.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()
希望这会有所帮助。
【讨论】:
【参考方案8】: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
【讨论】:
以上是关于从父类调用子组件方法 - Angular的主要内容,如果未能解决你的问题,请参考以下文章