【问题标题】:Populate dynamic forms with default data from api in Angular2在 Angular2 中使用来自 api 的默认数据填充动态表单
【发布时间】:2017-08-08 03:42:34
【问题描述】:

我已经使用 angular2 几个星期了,我正在尝试为系统设置页面创建动态表单。 目标:让 api 返回任意数量的表单,在选项卡内构建表单,表单可以具有任何 type 字段,并使用默认或以前保存的数据填充这些表单,然后修改和保存。

有效的方法:使用任意数量的输入字段创建任意数量的表单。 我需要用数据填充表单的帮助。 这是从 api 调用生成的项目。需要填充这些猫科动物的数据我需要一个单独的 api 调用。 请记住,每个表单都可以有多个这些输入

<li [formGroup]="form" class="form-control-item">
<div [ngSwitch]="item.controlType">
    <div *ngSwitchCase="'text'">
        <label class="text-lable " [for]="item.key">{{item.label}}</label>
        <div [ngSwitch]="item.controlType">
            <input [formControlName]="item.key" [id]="item.key" [type]="item.type" class="validate form-control input-lg" input name="{{ name }}" ng-model="name">
        </div>
    </div>
    <div *ngSwitchCase="'checkbox'">
        <label class="label-checkbox" [for]="item.key">{{item.label}}
            <input [formControlName]="item.key" name="{{ item.key }}" ng-model="name" type="checkbox" class="validate form-control checkbox-with-label" >
        </label>
    </div>
    <!--Needs testing with appropriate data-->
    <!--<div *ngSwitchCase="'dropdown'">-->
        <!--<label [for]="item.key">{{item.label}}</label>-->
        <!--<input [formControlName]="item.key" [id]="item.key" [type]="item.type" class="validate form-control input-lg">-->
        <!--<select [id]="item.key" [formControlName]="item.key">-->
            <!--<option *ngFor="let opt of item.options" [value]="opt.key">{{opt.value}}</option>-->
        <!--</select>-->
    <!--</div>-->
    <div *ngSwitchCase="'radio'">
        <label [for]="item.key">{{item.label}}</label>
        <input [formControlName]="item.key" [id]="item.key" [type]="item.type" class="validate form-control radio" name="{{ item.key }}" ng-model="name">
    </div>
    <div *ngSwitchCase="'password'">
        <label [for]="item.key">{{item.label}}</label>
        <input [formControlName]="item.key" [id]="item.key" [type]="item.type" class="validate form-control input-lg" name="{{ item.key }}" ng-model="name">
    </div>
</div>
<div class="errorMessage" *ngIf="!isValid">{{item.label}} is required</div>

这里是调用上述内容的组件:

@Component({
selector: 'dynamic-form',
templateUrl: 'dynamic-form.component.html',
styleUrls: ['./dynamic-form.component.scss']
})

export class DynamicFormComponent implements OnChanges {
    @Input() items: DynamicFormItemBase<any>[] = [];
    form: FormGroup;
    payLoad = '';

constructor(){
}

ngOnChanges(){
    this.form = this.toFormGroup(this.items);
}
ngOnInit(){
    this.form = this.toFormGroup(this.items);
}

onSubmit() {
    this.payLoad = JSON.stringify(this.form.value);
}

private toFormGroup(items: DynamicFormItemBase<any>[] ) {
    let group: any = {};
    items.forEach(item => {
        if(item.value.items){
            // console.log('has an internal item');
        }
        group[item.key] = new FormControl(item.value || '', item.required ? Validators.required : null);
        // console.log(item.value, 'has an internal item');
    });
    return new FormGroup(group);
}
}

再次澄清一下,我调用了一个 api 来获取将有多少表单及其名称。然后一个 api 调用按名称获取每个表单的布局(来自第一个 api 调用)。所有表格都可以构建。然后我有第三个 api 调用,它返回该表单的配置数据;我需要将此数据绑定到每个特定表单。

我无法创建典型的 ng-model="name" name="ng-model" #name 数据绑定方式。或者至少我不知道如何动态实现它。

 <tab class="{{module.name}}-tab" *ngFor="let module of Modules; let i = 

index" heading="{{module.displayName}}" (select)="beforeChange(module.name)">
 <div class="dynamic-form" > 
<dynamic-form [items]="items" >Loading...</dynamic-form> 
</div>

其中 items 是从 api 返回的。它的结构如下: 第一次调用是这样的

ModuleList  [{"name":"moduleName","displayName":"Module Name","enabled":true}]

其他一些不相关的代码运行,然后使用 maduleName 的参数进行 api 调用以返回布局

Array[
    0:Array[
        0:DynamicFormItemBase[
        controlType:"text"
        key:"inputID"
        label:"Input Id"
        order:1
        required:true
        value:ConfigItem [
            displayName:"Input ID"
            items:undefined
            name:"inputID"
            required:true
            type:"text"]
        ]
    ]

thirst API 调用(表单构建后)会调用不同的 api 方法,参数相同的 moduleName,并返回这样的对象

Object
    inputID:""
    inputID:1
    inputID:""
    inputID:"default text"
    enabled":true

其中每个 inputID 实际上是来自第二个 api 调用的标签 ID,而 enabled:true 应该针对第一个 api 调用的模块(当前存储在会话存储中)(如果数据不同,我将需要更新存储的项目)。

其中 api: items 被传递到动态表单组件中

<tab class="{{module.name}}-tab" *ngFor="let module of dpsModules; let i = index"
                  heading="{{module.displayName}}" (select)="beforeChange(module.name)">
                <div class="dynamic-form"  >
                    <dynamic-form [items]="items"  >Loading...</dynamic-form>
                </div>
            </tab>

【问题讨论】:

  • item.value 在您的toFormGroup 函数中有什么作用?那应该是表单控件的值。不是吗?你能以某种方式将配置值合并/包含在第二个 API 调用中吗?你至少有一个键可以用来匹配表单控件的配置值吗?
  • html中的每一项都是一个配置项数组。
  • 最好将这类内容添加到问题中,而不是在 cmets 中,因为太难阅读了。另外,那里还有更多的工作空间。您可以使用item.key(用作组数组中的索引)来查找从第三个 API 调用中获得的值吗?您要做的并不难,只要您可以将表单组数组与配置值链接在一起。
  • 提出问题,抱歉
  • 部分问题是这些表单在很多用例中需要是动态的,我无法在构建过程中添加其他值来填充默认数据。我需要一种将数据绑定到已经构建的表单的方法。我不确定我是否理解 如何 链接数组

标签: forms angular typescript dynamic api-design


【解决方案1】:

我从您的问题中收集到的内容是否正确,您从 third API 获得的数据应该具有您想要应用于根据您获得的信息构建的表单组的值在您的 API 调用中。

如果这是正确的,那么您需要遍历第三个 API 调用的结果并将值应用到表单组(应该在您开始时构建)。

我假设您熟悉 JavaScript/Typescript 中的循环/迭代。

我还将假设来自第三个 API 调用的数据具有一个字段或值,这将允许您识别需要将其值分配给的表单控件。对于这个演示,我将使用item.key 作为链接令牌。

这是您需要尝试的伪代码:

for each item.key 
  this.form.controls[item.key].value = item.value;

this.form 是您的组件中已有的东西。您可以使用其中的controls 集合以及一个索引值(在本例中为item.key)来读取或分配控件的value

如果您没有可以在第三个 API 调用中提供表单组和数据之间的链接的东西,那么绑定它们可能会很困难,如果不是不可能的话。如果你有的不仅仅是一个键,比如一个键和描述,你可以通过一些简单的连接来使用它。

希望对你有帮助!

【讨论】:

  • 我有点迷失了,“表单”有一个错误,该组件中不存在。该组件是进行 api 调用的组件。表单传递对象的代码在上方
  • 听起来你需要将你正在使用的服务注入到你上面的组件中,并调用你需要的数据。告诉我你知道这意味着什么,因为告诉你如何做到这一点超出了这个问题的范围。我假设您在使用 Angular 的短时间内已经掌握了其中的一些内容。
  • 我知道一些关于 DI,我希望有一种方法可以在动态表单组件之外执行此操作。因为该组件仅用于构建表单输入。虽然组件 systemSettings 说“嘿,我需要一些表单,但它们也有默认值”,但这种表单也用于创建用户页面,其中不会给出甚至要求没有默认值。我承认我在这里感觉有点超出我的深度,但我非常愿意并且渴望学习!在 systemSettings 的模板中,我将标签称为
  • 或.. 我不能扩展 上的@input perams 以包含 defaultValue="" 选项。并使这两个api调用同时发生?因此,当每次 foreach 迭代解决时,我传入一个表单项对象和一个值对象。动态表单调用标签 并传入每个单独的项目,我还可以扩展以包含匹配的默认值。它将始终为空,但被传入的 defaultValue 覆盖。意见?
  • 我的意见是我喜欢你前进的方向。这正是我过去所做的。在您的应用程序中,您必须将表单和数据放在一起。你如何做到这一点真的取决于你。我喜欢将服务用于 API 工作,将它们注入到组件中,将它们拼接在一起进行显示,以及不可避免地“转向另一条路”,将所有信息发送回存储。我会分享我过去所做的事情,但代码不是我要分享的。好资源:angular.io/docs/ts/latest/cookbook/dynamic-form.html
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2018-05-20
  • 2020-03-18
  • 2021-01-04
  • 1970-01-01
  • 1970-01-01
  • 2017-06-11
  • 2020-02-27
相关资源
最近更新 更多