Angular 动态组件:如何设置和获取数据
Angular Dynamic Components: How to Set and Get Data
我需要根据预先确定的类型动态创建组件,并能够设置和获取数据。
到目前为止,我能够创建和显示组件,但我不知道如何设置或从中获取数据。
这就是我添加和显示组件的方式:
app.component.ts:
export class AppComponent {
components: any[] = [];
constructor(private componentFactoryResolver: ComponentFactoryResolver) { }
addField(type: string) {
let component: any;
switch (type) {
case 'string':
// how to set data in the created component??
component = StringComponent;
break;
//...
}
const childComponent = this.componentFactoryResolver.resolveComponentFactory(component);
this.components.push(childComponent);
}
getComponentData() {
this.components.forEach(component => {
// how to access the data from each component??
});
}
}
app.component.html:
<div class="col-12" cdkDropList (cdkDropListDropped)="drop($event)">
<div cdkDrag *ngFor="let cmp of components">
<div class="row">
<div class="col-10">
<app-string *ngIf="cmp.selector == 'app-string'"></app-string>
<!-- (...) -->
</div>
<div class="col-2 field-btn pt-4">
<button type="button" mdbBtn color="danger" mdbWavesEffect>
<mdb-icon fas icon="times"></mdb-icon>
</button>
<button cdkDragHandle type="button" class="move" mdbBtn color="info" mdbWavesEffect>
<mdb-icon fas icon="arrows-alt"></mdb-icon>
</button>
</div>
</div>
</div>
</div>
string.component.ts:
export class StringComponent implements OnInit {
item = new Item();
constructor() { }
ngOnInit() {
}
}
string.component.html:
<div class="form-row mb-3">
<div class="form-group col-12 col-md-6">
<label for="name">Field Name</label>
<input mdbInput type="text" [(ngModel)]="item.value" class="form-control" id="name" placeholder="Field Name" (keyup)="onInputValueChange($event.target.value)">
</div>
<div class="form-group col-12 col-md-3">
<label for="identifier">Identifier</label>
<input mdbInput type="text" [(ngModel)]="item.id" class="form-control" id="identifier" placeholder="Autogenerated ID" disabled>
</div>
<div class="form-group col-12 col-md-3">
<label for="type">Type</label>
<input mdbInput type="text" class="form-control" id="type" placeholder="STRING" disabled>
</div>
</div>
动态添加的组件列表结果:
我没有使用 ng-template 添加组件,因为我可以将它们拖放到父组件的 cdkDropList 容器中。
我想要实现的是在将组件添加到列表之前设置 属性 'item.type' 的值,并能够获取每个组件 'item' 属性 在我填写他们的输入后。
设置和获取组件信息的最佳方法是什么?
更新:感谢@kari 的解决方案,我设法解决了我的问题。
这是结果:
我举例说明了如何使用 @Input()
和 @Output()
从动态组件传递和检索数据:https://stackblitz.com/edit/angular-z6wssp
我认为它按您想要的方式工作。
我基本上建议您将组件 和 数据都推送到您的组件数组:
compAndData.component = childComponent;
compAndData.data = data;
this.components.push(compAndData);
然后将数据传递给组件中的 @Input()
变量,并通过 EventEmitter
和 Output()
:
检索更改
<app-string [data]="cmp.data" (changedData)="onCompDataChanged($event)" *ngIf="cmp.component.selector === 'app-string'"></app-string>
尝试示例:更改字段名称,单击 GetComponentData 按钮并在控制台中检查检索到的数据。
我需要根据预先确定的类型动态创建组件,并能够设置和获取数据。 到目前为止,我能够创建和显示组件,但我不知道如何设置或从中获取数据。
这就是我添加和显示组件的方式:
app.component.ts:
export class AppComponent {
components: any[] = [];
constructor(private componentFactoryResolver: ComponentFactoryResolver) { }
addField(type: string) {
let component: any;
switch (type) {
case 'string':
// how to set data in the created component??
component = StringComponent;
break;
//...
}
const childComponent = this.componentFactoryResolver.resolveComponentFactory(component);
this.components.push(childComponent);
}
getComponentData() {
this.components.forEach(component => {
// how to access the data from each component??
});
}
}
app.component.html:
<div class="col-12" cdkDropList (cdkDropListDropped)="drop($event)">
<div cdkDrag *ngFor="let cmp of components">
<div class="row">
<div class="col-10">
<app-string *ngIf="cmp.selector == 'app-string'"></app-string>
<!-- (...) -->
</div>
<div class="col-2 field-btn pt-4">
<button type="button" mdbBtn color="danger" mdbWavesEffect>
<mdb-icon fas icon="times"></mdb-icon>
</button>
<button cdkDragHandle type="button" class="move" mdbBtn color="info" mdbWavesEffect>
<mdb-icon fas icon="arrows-alt"></mdb-icon>
</button>
</div>
</div>
</div>
</div>
string.component.ts:
export class StringComponent implements OnInit {
item = new Item();
constructor() { }
ngOnInit() {
}
}
string.component.html:
<div class="form-row mb-3">
<div class="form-group col-12 col-md-6">
<label for="name">Field Name</label>
<input mdbInput type="text" [(ngModel)]="item.value" class="form-control" id="name" placeholder="Field Name" (keyup)="onInputValueChange($event.target.value)">
</div>
<div class="form-group col-12 col-md-3">
<label for="identifier">Identifier</label>
<input mdbInput type="text" [(ngModel)]="item.id" class="form-control" id="identifier" placeholder="Autogenerated ID" disabled>
</div>
<div class="form-group col-12 col-md-3">
<label for="type">Type</label>
<input mdbInput type="text" class="form-control" id="type" placeholder="STRING" disabled>
</div>
</div>
动态添加的组件列表结果:
我没有使用 ng-template 添加组件,因为我可以将它们拖放到父组件的 cdkDropList 容器中。
我想要实现的是在将组件添加到列表之前设置 属性 'item.type' 的值,并能够获取每个组件 'item' 属性 在我填写他们的输入后。
设置和获取组件信息的最佳方法是什么?
更新:感谢@kari 的解决方案,我设法解决了我的问题。 这是结果:
我举例说明了如何使用 @Input()
和 @Output()
从动态组件传递和检索数据:https://stackblitz.com/edit/angular-z6wssp
我认为它按您想要的方式工作。
我基本上建议您将组件 和 数据都推送到您的组件数组:
compAndData.component = childComponent;
compAndData.data = data;
this.components.push(compAndData);
然后将数据传递给组件中的 @Input()
变量,并通过 EventEmitter
和 Output()
:
<app-string [data]="cmp.data" (changedData)="onCompDataChanged($event)" *ngIf="cmp.component.selector === 'app-string'"></app-string>
尝试示例:更改字段名称,单击 GetComponentData 按钮并在控制台中检查检索到的数据。