可以使用内容投影在Angular中将 @Input 对象传递给组件吗?

huangapple go评论59阅读模式
英文:

Is it possible to pass @Input object to a component using content projection in Angular?

问题

以下是翻译好的部分:

在 app.component 中,我想要做类似以下的操作:

<app-table-container [data]="tableData">
  <app-some-table></app-some-table>
</app-table-container>

table-container.component.html 中:

<!-- 还需要 data-object 的其他内容 -->
<ng-content [data]="data"></ng-content>

table-container.component.ts 中:

@Input() data: ITableStuff;

some-table.component.ts 中:

@Input() data: ITableStuff;

但这个方法不起作用。

我可以将 tableData 传递给 app.component 中的两者,但我想仅将其传递给 table-container,然后再传递给投影内容。

英文:

I want to do something like this in app.component:

&lt;app-table-container [data]=&quot;tableData&quot;&gt;
  &lt;app-some-table&gt;&lt;/app-some-table&gt;
&lt;/app-table-container&gt;

table-container.component.html

&lt;!-- stuff that also needs data-object --&gt;
&lt;ng-content [data]=&quot;data&quot;&gt;&lt;/ng-content&gt;

table-container.component.ts

@Input() data: ITableStuff;

some-table.component.ts

@Input() data: ITableStuff;

This doesn't work

I can pass the tableData to both in app.component but I'd like to pass it only to table-container and from there to projected content.

答案1

得分: 1

在app-some-table的构造函数中,您可以使用以下方式来访问父级并使用getter(而不是输入):

get data() {
   return this.tableComponent ? this.tableComponent.data : null;
}
constructor(@Host() @Optional() private tableComponent: AppTableComponent) {}

您还可以在ngAfterViewInit中使用getter来分配值:

export class ChildComponent implements AfterViewInit {
  data!: any;
  constructor(@Host() @Optional() private tableComponent: ParentComponent) {}
  
  ngAfterViewInit() {
    this.data = this.tableComponent ? this.tableComponent.data : null;
  }
}

另一种方法是使用ContentChild。在父组件中,您可以这样设置:

@ContentChild(ChildComponent) child!: ChildComponent;

然后在ngAfterViewInit中,可以这样做:

ngAfterViewInit() {
  setTimeout(() => {
    if (this.child)
      this.child.anotherData = this.data;
  });
}

请注意,这种方法需要知道"childComponent"类。您可以始终从一个组件基类扩展所有可能的子组件,并询问"ChildComponentBase"。

英文:

You can "reach" the parent using in constructor of app-some-table and use a getter (not an input)

get data()
{
   return this.tableComponent?this.tableComponent.data:null
}
constructor(@Host() @Optional() private tableComponent:AppTableComponent){}

You can also, instead use a getter assign the value in ngAfterViewOnInit

export class ChildComponent implements AfterViewInit{
  data!:any
  constructor(@Host() @Optional() private tableComponent:ParentComponent){}
  ngAfterViewInit()
  {
    this.data=this.tableComponent?this.tableComponent.data:null
  }
}

See stackblitz (in the stackblitz is the second option, I enclosed in a setTimeout when equal the data to avoid the error "Expression has changed after it was checked")

Update another approach is use ContentChild.

In our parent

 @ContentChild(ChildComponent) child!:ChildComponent

And in ngAfterViewInit

  ngAfterViewInit()
  {
    setTimeout(()=&gt;{
      if (this.child)
        this.child.anotherData=this.data
    })
  }

But this approach need know the "childComponent" class. Always can extends all the possibles child from a component base and ask about "ChildComponentBase"

答案2

得分: 0

以下是要翻译的内容:

这不是一件容易的事情,因为在这种情况下存在DI层次结构。

一种选择是使用 ContentChild/ContentChildren 来获取 some-table.component 的实例,并在 AfterContentInit 回调中分配其输入。

英文:

It is not straightforward because of DI hierarchy in this case.

One option is to use ContentChild/ContentChildren to get instance of some-table.component and assign its input in AfterContentInit callback.

huangapple
  • 本文由 发表于 2023年6月29日 14:29:42
  • 转载请务必保留本文链接:https://go.coder-hub.com/76578530.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定