包装或扩展 angular-material 组件,允许将未知属性传递给子组件

Posted

技术标签:

【中文标题】包装或扩展 angular-material 组件,允许将未知属性传递给子组件【英文标题】:Wrap or extend angular-material component allowing pass-through of unknown attributes to child component 【发布时间】:2018-10-24 06:24:09 【问题描述】:

我们正在使用 Angular 5 和材料设计,并使用各种功能的辅助方法创建我们自己的组件(即为mat-table 生成动态列)。

我想要一种将未知属性从父组件传递到子组件的方法。这在 React 中很容易,例如:

应用类渲染

<MyDatatable knownVar="1" otherKnownVar="2" unknownButKnownToChildVar="3" />

MyDataTable 渲染

<MatComponent ...this.props />

这样,如果MatComponent 更新了它所接受的属性,MyDataTable 就不必更新了。我查看了 @Input 装饰器,但这似乎并不能促进未知变量。

我想到的一个解决方案是只传入一个对象并通过@Input 说明该对象,但我不喜欢这样,因为我希望 angular-material 组件文档能够准确地反映开发人员应该如何正在使用 my MyDataTable 组件。

我的问题的简短版本:如何在 Angular 5 中将未说明的属性级数据传递给子组件?

【问题讨论】:

这在 Angular 中不存在,也不适用于 AoT。 如果您不想在数据发生变化时更改子组件,那么您肯定必须知道提供的是哪种数据。就像一个人组件将接收一个人作为输入。不过,您可以提供尽可能多的输入。因此,您可以定义所有已知的输入,并定义一个额外的输入来执行您在解决方案中描述的操作。 未知变量不能是对象类型,以便将来它可以包含对象属性形式所需的属性吗? 技术上是的,这就是我在问题的建议解决方案部分中所涵盖的内容。但是,这不会让您在任何名称的组件上提供属性。如果没有在MyAngComponent 类中专门为unknownAttribute 提供@Input 选择器,&lt;MyAngComponent unknownAttribute="1"&gt; 将无法传递给子组件 一年后,你能解决这个问题吗? 【参考方案1】:
<div class="example-container mat-elevation-z8">
      <table mat-table #table [dataSource]="dataSource">

        <!--- Note that these columns can be defined in any order.
              The actual rendered columns are set as a property on the row definition" -->

        <!--  Column -->
        <ng-container matColumnDef="column">
          <th mat-header-cell *matHeaderCellDef> column </th>
          <td mat-cell *matCellDef="let element"> element.symbol </td>
        </ng-container>

        <tr mat-header-row *matHeaderRowDef="displayedColumns"></tr>
        <tr mat-row *matRowDef="let row; columns: displayedColumns;"></tr>
      </table>
    </div>

Sample.html

只需传递可能来自父组件或子组件的数据源对象。

数据源 = 数据;

希望你明白我的意思,或者你需要一些不同的东西。根据您的问题,动态数据插入到您的表必须绑定到控制器部分。就角度而言,如果您的数据源模型由子组件和父组件更新。它会在更新发生时呈现数据。

如果可能,显示您的父子组件数据的代码? 谢谢

【讨论】:

这只是一个例子。问题是关于通过父组件未知但子组件知道 的属性发送数据。 目前在 Angular 中没有任何方法可以做到这一点。至少我知道。您可以像上面提到的那样执行一些变通方法,或者使用服务为您的组件提供您想要的任何数据。但是 Angular 不会让你将未知属性传递给组件。【参考方案2】:

我能想到的使用 Angular 提供的 Input 装饰器做你想做的事情的一种方法是将 JS 对象 (any) 传递到组件输入中,并根据属性执行所需的代码。示例:

my-component.component.ts

import  Component, OnInit, Input  from '@angular/core';

@Component(
  selector: 'my-component',
  templateUrl: './my-component.component.html',
  styleUrls: ['./my-component.component.css']
)
export class MyComponentComponent implements OnInit 
  @Input() data: any;
  constructor()  
  ngOnInit()  

app.component.html

<my-component [data]="data: 2, extraData: 3"></my-component>

在这种情况下,您可以在输入数据中添加 n* 个属性。没有将未知数量的属性传递给组件的任何实现。

您还可以做的另一件很酷的事情是在您的组件内部,您实际上可以有一些默认值,并且还可以期待更多。就像这里的例子:

app.component.html

<my-component [data]="name: 'John', surname: 'Doe'"></my-component>

my-component.component.ts

import  Component, OnInit, Input  from '@angular/core';

@Component(
  selector: 'my-component',
  templateUrl: './my-component.component.html',
  styleUrls: ['./my-component.component.css']
)
export class MyComponentComponent implements OnInit 
  @Input() data: any;
  constructor()  
  ngOnInit() 
    this.data = 
      name: "John",
      surname: "Doe",
      origin: "UK",
      ...this.data
    
  

my-component.component.html

<div *ngIf="data.phone">
  Phone Number:  data.phone 
</div>

或者甚至制作某种 Object.keys(this.data) 并遍历数据属性并打印正确的 html。这样,您可以为已知属性设置一些默认值,甚至可以期待更多未知属性。

希望对我有所帮助。

【讨论】:

这是我提出的解决方案的一个很好的实现,但是我想我的问题的真正答案是你(和其他评论者)在你说:“没有任何实现将未知数量的属性传递给组件。”

以上是关于包装或扩展 angular-material 组件,允许将未知属性传递给子组件的主要内容,如果未能解决你的问题,请参考以下文章

如何从 angular-material2 对话框与其父级进行通信

扩展 Kendo Angular 2 UI 组件并创建我们自己的具有所有 Kendo 组件功能的组件包装器

我是不是需要(或应该)将我所有的 Vue 组件包装在一个包装器组件中?

什么是包装类?

按单词包装 UILabel 并以编程方式扩展 UITableViewCell 高度

Flutter中常用的组件-Expanded