angular 5 从父组件设置子组件属性

Posted

技术标签:

【中文标题】angular 5 从父组件设置子组件属性【英文标题】:angular 5 setting child component property from parent component 【发布时间】:2019-05-05 13:15:38 【问题描述】:

我想从父组件设置子组件属性

parent.component.html

<div>
<child-detail #myCarousel [childList]="detail.List" ></child-detail>
</div>  

parent.component.ts

@Component(
  selector: "parent",
  templateUrl: "./parent.component.html",
 )  
export class AppComponent  
  public detail; // it is of JSON type

child.component.ts

@component(
 selector:'child-detail',
 templateUrl: './child.component.html'
)
export class ChildDetailComponent
  @Input() public childList;   // that list of array type

child.component.html

<div *ngFor = "let list of childList">
 <li>list </li>
</div>

我知道我可以通过@Input() 绑定设置此属性,但这只会在组件初始化时设置,我想在某个时候以编程方式在中间设置它。

我知道我可以使用

访问父级中的这个子属性
@ViewChild(ChildDetailComponent) childDetailComponent: ChildDetailComponent;
console.log(this.childDetailComponent.childList);

但我想在任何父母事件中以编程方式设置它。

【问题讨论】:

那么为什么不能使用input 属性并在父事件上填充该输入属性? *但这只会在组件初始化时设置 *??这不是真的。每当您更改父项中的道具时,都会设置它。阅读ngOnChanges()钩子 @xyz 你能详细说明一下吗? 当父组件中childList的值发生变化时,childComponent中的childList的值也将被更新,但是如果你去更改父组件中childList的值childList 的值在子组件中发生变化,您可以对childList 使用set 方法Input 只是一个注释。您正在使用 TypeScript。 TypeScript 有类型。那么为什么不使用// that list of array type,而是正确声明变量的类型呢? 【参考方案1】:

如果不使用 @Input 属性,我不确定您是如何做到的。

每当您传递给它的输入发生变化时,它也会反映在子组件中。您可以在子组件中的ngOnChanges 中跟踪它。试试logging 到console

试试这个:

import  Component  from '@angular/core';

@Component(
  selector: 'my-app',
  templateUrl: './app.component.html',
  styleUrls: [ './app.component.css' ]
)
export class AppComponent  
  detail: any = 
    childList: []
  ;

  setChildList() 
    this.detail.childList = [
       id: 1, name: 'John' ,
      ...
    ];
  


在模板中:

<button (click)="setChildList()">Set Child List</button>
<hello [childList]="detail.childList"></hello>

这里@Input 属性在单击按钮时发生变化。但在您的情况下,您可以简单地将 setChildList 方法称为您的事件。


这里有一个Working Sample StackBlitz 供您参考。

【讨论】:

但是 ngOnChanges() 只检测到主要类型的变化,所以这个生命周期钩子会运行,但是如果对象属性发生变化,它就不会运行。 从您所说的来看,您的组件上似乎有一个 ChangeDetectionStrategyOnPush。在这种情况下,它只会在 @Input 对象的引用发生变化时运行。 在这种情况下,您所说的没有任何意义。我正在将输入传递给子组件,就像您想要的那样。如果您查看我的 StackBlitz 示例,它会按预期传递值并在子组件中更新它。 您可以查看以下网址concretepage.com/angular-2/…。 (如果对象属性发生变化,此技术将不起作用) 您是否检查过 StackBlitz 示例?将对象作为@Input 传递正是我在那里所做的。它正在检测更改并更新子组件以及视图。【参考方案2】:

您可以务实地使用服务来共享数据。

第 1 步:创建数据共享服务。

import  Injectable  from '@angular/core';
import  BehaviorSubject  from 'rxjs';

@Injectable()
export class DataService 

  private messageSource = new BehaviorSubject('default message');
  currentMessage = this.messageSource.asObservable();

  constructor()  

  changeMessage(message: string) 
    this.messageSource.next(message)
  

 

第 2 步:更改消息

export class ParentComponent implements OnInit 

  message:string;

  constructor(private data: DataService)  

  ngOnInit() 
   this.data.changeMessage("Hello from Sibling")
  

第 3 步:获取消息

export class ChildComponent implements OnInit 

  message:string;

  constructor(private data: DataService)  

  ngOnInit() 
    this.data.currentMessage.subscribe(message => this.message = message)
  


【讨论】:

您应该在 app.module.ts 中的providers: [DataService] 添加DataService,否则会出现以下错误NullInjectorError: No provider for DataService!【参考方案3】:

在子组件中使用@input。可以使用ngOnChanges监听子组件的变化。

@Input() name: string;

ngOnChanges(changes: SimpleChanges) 
  const name: SimpleChange = changes.name;
  console.log('prev value: ', name.previousValue);
  console.log('got name: ', name.currentValue);

工作stackblitz

【讨论】:

以上是关于angular 5 从父组件设置子组件属性的主要内容,如果未能解决你的问题,请参考以下文章

从Angular 2中的子组件更新父组件属性

如何将 Angular 5 中的点击数据从父组件传递到子组件?

Angular 2 @Input - 如何从父组件绑定子组件的 ID 属性?

如何在Angular 5中从父组件继承子组件中的css样式

在视图呈现之前从父级设置子组件属性

Angular 2 单元测试数据从父组件传递到子组件