如何在 AngularJS 表单中嵌套 Angular 2+ 表单?
Posted
技术标签:
【中文标题】如何在 AngularJS 表单中嵌套 Angular 2+ 表单?【英文标题】:How can I nest an Angular 2+ form inside an AngularJS form? 【发布时间】:2020-08-06 18:05:54 【问题描述】:我正在努力将一个大型 AngularJS 应用程序升级到 Angular 5+。这意味着在混合 AngularJS 应用程序中使用新的 Angular 5 组件。在许多情况下,表单嵌套在其他表单中。旧的 AngularJS 代码有这样的父表单:
export default function PersonDirective()
return
restrict: "E",
template: `
<div ng-form="personForm">
<input type="text" name="surname" ng-model="person.surname" ng-required="true">
<address-form address="person.homeAddress"></address-form>
</div>`,
replace: true,
scope:
person: "="
;
和子窗体类似:
export default function AddressDirective()
return
restrict: "E",
template: `
<div ng-form="addressForm">
<input type="text" name="firstLine" ng-model="address.firstLine" ng-required="true">
<input type="text" name="city" ng-model="address.city" ng-required="true">
</div>`,
replace: true,
scope:
address: "="
;
这会为 PersonDirective 生成一个 FormController,它的地址表单是一个名为 addressForm
的嵌套 FormController 字段。子表单中的验证错误会影响父表单的有效性。
我已将地址表单转换为 Angular 5 组件,将 AngularJS ng-form
和 ng-required
指令替换为标准 html:
@Component(
selector: 'address-form',
template: `
<div>
<form #addressForm="ngForm">
<input type="text" name="firstLine" [(ngModel)]="address.firstLine" required>
<input type="text" name="city" [(ngModel)]="address.city" required>
</div>`
)
export class AddressFormComponent
@Input() address: any;
新组件在index.ts
中降级以在AngularJS 中使用:
angular.module('common')
.directive("ng2AddressForm", downgradeComponent(component: AddressFormComponent));
以及修改为使用新组件的 PersonDirective 模板:
<div ng-form="personForm">
<input type="text" name="surname" ng-model="person.surname" ng-required="true">
<ng2-address-form address="person.homeAddress"></ng2-address-form>
</div>
新组件按预期显示和验证。问题是它不再作为字段出现在父表单中,其有效性和状态也不再传播给父表单。一次转换所有表格是不可能的。任何人都可以提出解决方案吗?
【问题讨论】:
在这个过程中使用 Angular Elements 怎么样? 【参考方案1】:我找到的最佳解决方案是创建一个实现 ControlValueAccessor 和 Validator 的子组件。 ControlValueAccessor 允许使用新 Angular 2+ 模板中的 [(ngModel)] 和旧 AngularJS 模板中的 ng-model 将组件绑定到任意对象(上面示例中的地址)。
在新模板中,子组件的有效性状态会自动影响父表单的有效性。在 AngularJS 中,我不得不使用事件处理程序向父级报告子级状态。所以关系看起来是这样的:
在 AngularJS 父表单模板中:
<ng2-address-form
ng-model="myCtrl.person.homeAddress"
(status)="myCtrl.onAddressStatus($event)">
</ng2-address-form>
在 Angular 2+ 组件中:
export class AddressFormComponent implements ControlValueAccessor, Validator
@Output("status") statusEvent = new EventEmitter<ValidationErrors | null>();
addressForm: FormGroup;
...
this.addressForm.statusChanges.subscribe(s => this.statusEvent.emit(this.validate(null)));
...
validate(c: AbstractControl): ValidationErrors | null
// validate the form
我发现使用响应式表单更容易,因为它使组件逻辑可以直接访问表单控件。
【讨论】:
以上是关于如何在 AngularJS 表单中嵌套 Angular 2+ 表单?的主要内容,如果未能解决你的问题,请参考以下文章
构建混合 angular/angularjs 应用程序 - 如何在 angularjs 应用程序中加载 Angular 模块