如何在Angular中创建复杂的动态表单?

WEB前端开发社区 昨天

表单是Web应用程序中非常重要的部分。有时我们会遇到一个情况,即form元素是静态的并且定义明确。有时,Web应用程序开发会从静态形式扩展到动态形式。动态表单没有静态字段。

动态表单和控件可以基于某些事件生成。在本文中,我们将基于单击加号生成控件。单击减号按钮将其删除。

这是一种类似于芯片的结构,其中我们具有加号和减号按钮来添加和删除文本字段。在本文中,我们以产品为例。

角度设计

Angular支持两种动态控制设计。

  • 模板驱动-在模板驱动的表单中,可以更好地控制角度模板。该模板非常强大,并且具有Angular框架内置的大多数功能。我们只需要手工设计出干净整洁的HTML。我自由也正在使用这种方法。

  • 反应形式-同样非常强大,大多数控件位于组件中。需要Formbuilder来构建表单。

构建动态组件

我们正在构建产品组件。该产品具有产品名称和产品代码。该产品还有另一个可选参数,即产品功能。产品功能部件包含功能部件名称,功能部件添加日期和功能部件说明。

这些功能可以随时添加。我们要添加的功能数量没有限制。如下所示:

模型设计

创建界面产品功能并将其传递到产品界面。产品界面采用了诸如数组之类的产品功能。下面是数据模型。

    export interface productFeatures{  featureName:string,  featureAddedDate:string,  featureDescription?:string}export interface Product<productFeatures> {    id: number | null;    productName: string;    productCode: string;    description?: string;    productFeatures?: productFeatures[];} export const products: Product<productFeatures>[] = [  {      id: 1,                productName: 'Netgear Cable Modem',                productCode: 'CM700',                description: 'Netgear Cable Modem compatible with all cables',                productFeatures: [{                  featureName:"",                  featureAddedDate:"",                  featureDescription:""                  }]             },                    ];

    接着就是创建一个子组件。是的,我在这里创建一个子组件。因为在大多数企业应用程序中,我们应该创建一小组组件。

      <app-product-feature> </ app-product-feature>

      我们必须将数据从子组件传递到父组件。因此,这里定义了parentProductFields函数,该函数将数据设置为父组件。

        <app-product-feature(parentProductFields)=“ parentProductFields($ event)”> </ app-product-feature>

        在父组件中创建方法parentProduct。此方法将设置this.productField,其类型为Product <productFeatures>。

          productField: Product<productFeatures> = {} as Product<productFeatures>;parentProductFields(value) {console.log(`calling hour recieved from parent is ${JSON.stringify(value)}`)this.productField = value;}

          现在,在目录product下创建子组件产品功能。将父产品字段定义为@Output属性。parentProductFields的类型为Product <productFeatures>。

            @Output() parentProductFields = new EventEmitter<Product<productFeatures>>()

            用初始数据初始化。在这里,产品ID初始化为1,其余字段初始化为空。每当添加新功能时,产品功能数组都会包含一个对象,我们将在功能数组中推送一个新功能对象。

              productField: Product<productFeatures> = {id: 1,productName: '’,productCode: '’,description: '’,productFeatures: [{featureName:””,featureAddedDate:””,featureDescription:””}]}

              完整的产品组件将如下所示。

                import { Component, Input, Output,EventEmitter } from '@angular/core';import {Product,productFeatures} from './product';@Component({  selector: 'app-product-feature',  templateUrl: "./product-feature.component.html"})export class ProductFeatureComponent {@Input() childProductField: Product<productFeatures>;@Output() parentProductFields = new EventEmitter<Product<productFeatures>>();  productField: Product<productFeatures> = {            id: 1,            productName: '',            productCode: '',            description: '',            productFeatures: [{              featureName:"",              featureAddedDate:"",              featureDescription:""          }]    }addNewProdField(index: number): void {let prod: productFeatures =  {"featureName": "","featureAddedDate": "","featureDescription": ""    } ;this.productField.productFeatures.push(prod);console.log(`In method  addNewProdField field index is ${index} and field is ${JSON.stringify(JSON.stringify( this.productField))}`);this.parentProductFields.emit(this.productField);  }  removeNewProdField(index: number): void {this.productField.productFeatures.splice(index, 1);console.log(`In method  addNewProdField field index is ${index}`);this.parentProductFields.emit(this.productField);  }}

                现在开始写HTML结构。在HTML产品名称中,产品代码为文本框。产品功能是我们迭代以生成动态组件的动态表。

                  <tbody><ng-template ngFor let-prod [ngForOf]=”productField.productFeatures” let-i=”index”><tr><td><!-- Product feature here --><td></tr></ng-template></tbody>

                  在开发此控件时,发现了一件重要的事情。你必须为每个控件动态创建ID。否则,将创建该控件的相同深层副本。

                    <td><input class=”form-control minimal” id=”{{featureAddedDate + prod}}”[(ngModel)]=”prod.featureAddedDate”></td>

                    完整的HTML文件如下所示。

                      <h5>Product component</h5><div class="row">  <div class="col-md-12"> </div></div><div class="row">  <div class="col-md-12"> </div></div><div class="row required-field">  <div class="col-md-4">    <label class="cus-form-label">Product Name</label>    <input class="form-control minimal" id="productName"            [(ngModel)]="productField.productName">  </div></div><div class="row">  <div class="col-md-12"> </div></div><div class="row required-field">  <div class="col-md-4">    <label class="cus-form-label">Product Code</label>    <input class="form-control minimal" id="productCode"            [(ngModel)]="productField.productCode">  </div></div><div class="row">  <div class="col-md-12"> </div></div><label class="cus-form-label">Product Features</label><div class="row">  <div class="col-md-12"> </div></div><table class="col-lg-8" id="callingHours-id" style="background-color: white;">  <thead>    <tr>      <th class="bordered-cell" style="width: 30%;">Feature Name</th>      <th class="bordered-cell">Feature Date</th>          <th class="bordered-cell">Feature Description</th>    </tr>  </thead>  <tbody>    <ng-template ngFor let-prod [ngForOf]="productField.productFeatures" let-i="index">      <tr>        <td>        <input class="form-control minimal" id="{{name + prod}}"            [(ngModel)]="prod.featureName">        </td>        <td>        <input class="form-control minimal" id="{{featureAddedDate + prod}}"            [(ngModel)]="prod.featureAddedDate">        </td>         <td>        <input class="form-control minimal" id="{{featureDescription + prod}}"            [(ngModel)]="prod.featureDescription">        </td>        <td>    <ng-container>      <button id="{{'remoeMinus' +i}}" class="btn btn-xs btn-danger" (click)="removeNewProdField(i)">                      <i class="fa fa-minus"></i>                    </button>    </ng-container>     <ng-container>       <button id="{{'addrec'+ i }}" class="btn btn-xs btn-primary" (click)="addNewProdField(i)">              <i class="fa fa-plus"></i>              </button>    </ng-container>        </td>      </tr>    </ng-template>  </tbody></table>

                      添加产品功能

                      要添加新产品功能,请添加以下代码。此方法向this.productField.productFeatures添加新功能产品

                        addNewProdField(index: number): void {let prod: productFeatures = {“featureName”: “”,“featureAddedDate”: “”,“featureDescription”: “”} ;this.productField.productFeatures.push(prod);console.log(`In method addNewProdField field index is ${index} and field is ${JSON.stringify(JSON.stringify( this.productField))}`);this.parentProductFields.emit(this.productField);}

                        删除产品功能

                        要删除产品功能,请从this.productField.productFeatures中拼接产品索引。

                          removeNewProdField(index: number): void {this.productField.productFeatures.splice(index, 1);console.log(`In method addNewProdField field index is ${index}`);this.parentProductFields.emit(this.productField);}

                          要显示子组件数据中的更改,请在父组件HTML中添加以下行。

                            <pre>{{productField | json}}</ pre>

                            现在,你可以看到添加的字段的JSON数据。

                              {  "id": 1,  "productName": "Netgear Wireless Router",  "productCode": "NG123",  "description": "",  "productFeatures": [    {      "featureName": "capacity",      "featureAddedDate": "05/01/2020",      "featureDescription": "123"    },    {      "featureName": "range",      "featureAddedDate": "05/01/2020",      "featureDescription": "123"    }  ]}

                              总结

                              同样,我们可以将示例扩展为多个产品。创建产品数组并使用* ngFor循环进行显示。在这种情况下,我们应该有两个索引。

                              产品的一个索引和其他产品功能。产品索引将有助于添加到产品阵列中,而功能索引将有助于添加/删除产品功能。

                              在stackblitz项目中附加完整的代码示例,截图如下:

                              来源:
                              https://medium.com/javascript-in-plain-english/how-to-create-a-complex-dynamic-form-in-angular-19a472af6060
                              不看的原因确定内容质量低不看此公众号
                              (0)

                              相关推荐