递归动态Angular形式;从 Deeper Child 到 Root(Parent 组件)的 EmitEvent
Recursive Dynamic Angular Form; EmitEvent from Deeper Child to Root (Parent Component)
嗨,我是新手,我正在创建一个 Reactive Form
的项目;基于 Recursive
从 JSON
文件创建 Dynamic Form
的组件。来源
这是基于 Creating Dynamic Angular Forms with JSON 的 Ionic 改编版
我改编了递归版本程序和其他更改!
我的代码位于 Stackblitz.
我的组件 SelectsComponent
位于 selects.component.ts 文件中,具有选择器 selector: 'selects',
我有:
@Output() addControl = new EventEmitter<JsonFormControls>();
和方法
public onSelectChange(event: MatSelectChange) {
console.log(this.form.value);
console.log('parent:' + this.parentControl || 'root');
this.control.value = event + '';
if (this.control.children) {
this.recursiveConcealer(this.control.children);
const child = this.control.children.find(
(child) => child.value === event + ''
);
this.newControl(child);
if (child.siblings) {
for (let sibling of child.siblings) {
this.newControl(sibling);
}
}
//Emit Event to Root
this.addControl.emit(child);
}
}
当调用onSelectChange
方法时,则执行emit this.addControl.emit(child);
在template
selects.component.html文件中,我有这样的代码:
<ng-container *ngFor="let child of control?.children">
<div fxFlex="100%">
<selects
*ngIf="child.type === 'select'"
[control]="child"
[parentControl]="control"
[formBuilder]="formBuilder"
></selects>
</div>
</ng-container>
我的 JsonFormComponent
位于 json-form.component.ts 文件中,其中这个方法:
public onAddControl(addControlEvent: JsonFormControls) {
this.addControl(addControlEvent);
addControlEvent.visible = true;
}
在template
json-form.component.html文件中,代码如下:
<selects
*ngIf="control.type === 'select'"
[control]="control"
[visible]="true"
(addControl)="onAddControl($event)"
[formBuilder]="myFormBuilder"
></selects>
当某些 Child-component (SelectsComponent
) 不是 Root Parent-Component (JsonFormComponent
) 的直子时出现问题,可能是孙子或同级关系, 如:
(0级)JsonFormComponent
-> (1级)SelectsComponent
-> (2级)SelectsComponent
-> (3级)SelectsComponent
如何re-emit从SelectsComponent
child到SelectsComponent
parent.
问题:
- 如何从(级别 3)
SelectsComponent
发送或发出事件到(级别 0)JsonFormComponent
?
- 如何将一些确认事件从(级别 0)
JsonFormComponent
发送到(级别 3)SelectsComponent
?
提前致谢!
我很欣赏不是基于 services
的答案,我知道这可能是一个替代方案。
编辑:
预期的 Console.log(...)
是多少?
console.log(`parent: ${this.parentControl?this.parentControl.name:'root'} -> control.name: ${this.control.name} -> Emitter: ${e?.name}` );
第一个(或根)组件是 company
类似于:
parent: root -> control.name: company -> {Here the last node child}.
根据上图点击
第一次点击(第一级):
parent: root -> control.name: company -> Emitter: Petitioner (C2 -> P2).
第二次点击(二级):
parent: root -> control.name: company -> Emitter: Service (C2 -> P2 -> S2).
示例:第 3 次点击(第三级):
parent: root -> control.name: company -> Emitter: Request (C2 -> P2 -> S2 -> R2).
console.log(或未来的操作)只会在根(即company
)的上下文中执行。
你的问题有答案(我希望);
可以给自己注入SelectsComponent:
@Optional() @SkipSelf() private selectsComponent: SelectsComponent
然后订阅自己的 addControl EE 并将他的值推送到注入的实例:
ngOnInit(): void {
if (this.selectsComponent) {
this.addControl
.subscribe(e => {
this.selectsComponent.addControl.next(e);
});
}
this.form = this.rootFormGroup.form;
}
在这种情况下,您正在同步所有嵌套的 EE;
- 对于你的第二个问题,我认为解决方案是将 data/subject 传递到每个 SelectComponent 的 Input 装饰器中(绑定到 children 选择你进入主机组件的输入数据)。
我已经准备了一个示例来说明您的第一个问题是如何工作的,请检查 SelectsComponent。看到每个子组件触发他的父 addControl:Stackblitz
这是 https://stackblitz.com/edit/angular-ivy-6kccps
中的更新解决方案
1.How 从(级别 3)SelectsComponent 向(级别 0)JsonFormComponent 发送或发出事件?
监听 selects.component.html
子组件 selects
发出的 addControl 事件
<selects
*ngIf="child.type === 'select'"
[control]="child"
[parentControl]="control"
[formBuilder]="formBuilder"
(addControl)="handleAddControl($event)"
></selects>
发出事件
handleAddControl(data: any) {
this.addControl.emit(data);
}
这将从 SelectsComponent
的每个实例发送事件,以冒泡到顶部 JsonFormComponent
2.How 从(级别 0)JsonFormComponent 向(级别 3)SelectsComponent 发送一些确认事件?
我不太确定发送确认需要什么。但是,我假设在原始实例中收到确认后您将执行某些操作,例如更新一些 属性。可以通过向事件有效负载添加回调来实现,如下所示:
selects.component.ts
//Emit Event to Root
public onSelectChange(event: MatSelectChange) {
...
...
...
const data = {child,
callback: () => {
console.log('Executing callback for control with label', this.control.name)
}
}
this.addControl.emit(data);
执行json-form中的回调。component.ts
public onAddControl(addControlEvent: any) {
if (addControlEvent.callback) {
addControlEvent.callback();
}
this.addControl(addControlEvent);
addControlEvent.visible = true;
}
嗨,我是新手,我正在创建一个 Reactive Form
的项目;基于 Recursive
从 JSON
文件创建 Dynamic Form
的组件。来源
这是基于 Creating Dynamic Angular Forms with JSON 的 Ionic 改编版
我改编了递归版本程序和其他更改! 我的代码位于 Stackblitz.
我的组件 SelectsComponent
位于 selects.component.ts 文件中,具有选择器 selector: 'selects',
我有:
@Output() addControl = new EventEmitter<JsonFormControls>();
和方法
public onSelectChange(event: MatSelectChange) {
console.log(this.form.value);
console.log('parent:' + this.parentControl || 'root');
this.control.value = event + '';
if (this.control.children) {
this.recursiveConcealer(this.control.children);
const child = this.control.children.find(
(child) => child.value === event + ''
);
this.newControl(child);
if (child.siblings) {
for (let sibling of child.siblings) {
this.newControl(sibling);
}
}
//Emit Event to Root
this.addControl.emit(child);
}
}
当调用onSelectChange
方法时,则执行emit this.addControl.emit(child);
在template
selects.component.html文件中,我有这样的代码:
<ng-container *ngFor="let child of control?.children">
<div fxFlex="100%">
<selects
*ngIf="child.type === 'select'"
[control]="child"
[parentControl]="control"
[formBuilder]="formBuilder"
></selects>
</div>
</ng-container>
我的 JsonFormComponent
位于 json-form.component.ts 文件中,其中这个方法:
public onAddControl(addControlEvent: JsonFormControls) {
this.addControl(addControlEvent);
addControlEvent.visible = true;
}
在template
json-form.component.html文件中,代码如下:
<selects
*ngIf="control.type === 'select'"
[control]="control"
[visible]="true"
(addControl)="onAddControl($event)"
[formBuilder]="myFormBuilder"
></selects>
当某些 Child-component (SelectsComponent
) 不是 Root Parent-Component (JsonFormComponent
) 的直子时出现问题,可能是孙子或同级关系, 如:
(0级)JsonFormComponent
-> (1级)SelectsComponent
-> (2级)SelectsComponent
-> (3级)SelectsComponent
如何re-emit从SelectsComponent
child到SelectsComponent
parent.
问题:
- 如何从(级别 3)
SelectsComponent
发送或发出事件到(级别 0)JsonFormComponent
? - 如何将一些确认事件从(级别 0)
JsonFormComponent
发送到(级别 3)SelectsComponent
?
提前致谢!
我很欣赏不是基于 services
的答案,我知道这可能是一个替代方案。
编辑:
预期的 Console.log(...)
是多少?
console.log(`parent: ${this.parentControl?this.parentControl.name:'root'} -> control.name: ${this.control.name} -> Emitter: ${e?.name}` );
第一个(或根)组件是 company
类似于:
parent: root -> control.name: company -> {Here the last node child}.
根据上图点击
第一次点击(第一级):
parent: root -> control.name: company -> Emitter: Petitioner (C2 -> P2).
第二次点击(二级):
parent: root -> control.name: company -> Emitter: Service (C2 -> P2 -> S2).
示例:第 3 次点击(第三级):
parent: root -> control.name: company -> Emitter: Request (C2 -> P2 -> S2 -> R2).
console.log(或未来的操作)只会在根(即company
)的上下文中执行。
你的问题有答案(我希望);
可以给自己注入SelectsComponent:
@Optional() @SkipSelf() private selectsComponent: SelectsComponent
然后订阅自己的 addControl EE 并将他的值推送到注入的实例:
ngOnInit(): void {
if (this.selectsComponent) {
this.addControl
.subscribe(e => {
this.selectsComponent.addControl.next(e);
});
}
this.form = this.rootFormGroup.form;
}
在这种情况下,您正在同步所有嵌套的 EE;
- 对于你的第二个问题,我认为解决方案是将 data/subject 传递到每个 SelectComponent 的 Input 装饰器中(绑定到 children 选择你进入主机组件的输入数据)。
我已经准备了一个示例来说明您的第一个问题是如何工作的,请检查 SelectsComponent。看到每个子组件触发他的父 addControl:Stackblitz
这是 https://stackblitz.com/edit/angular-ivy-6kccps
中的更新解决方案1.How 从(级别 3)SelectsComponent 向(级别 0)JsonFormComponent 发送或发出事件?
监听 selects.component.html
子组件selects
发出的 addControl 事件
<selects
*ngIf="child.type === 'select'"
[control]="child"
[parentControl]="control"
[formBuilder]="formBuilder"
(addControl)="handleAddControl($event)"
></selects>
发出事件
handleAddControl(data: any) {
this.addControl.emit(data);
}
这将从 SelectsComponent
的每个实例发送事件,以冒泡到顶部 JsonFormComponent
2.How 从(级别 0)JsonFormComponent 向(级别 3)SelectsComponent 发送一些确认事件?
我不太确定发送确认需要什么。但是,我假设在原始实例中收到确认后您将执行某些操作,例如更新一些 属性。可以通过向事件有效负载添加回调来实现,如下所示: selects.component.ts
//Emit Event to Root
public onSelectChange(event: MatSelectChange) {
...
...
...
const data = {child,
callback: () => {
console.log('Executing callback for control with label', this.control.name)
}
}
this.addControl.emit(data);
执行json-form中的回调。component.ts
public onAddControl(addControlEvent: any) {
if (addControlEvent.callback) {
addControlEvent.callback();
}
this.addControl(addControlEvent);
addControlEvent.visible = true;
}