Angular dynamic form (linked and displayed according to the selection)

Angular dynamic form (linked and displayed according to the selection)

First of all

Record it just completed a feature

Again demonstrated the parent after demand is made according to a fixed hierarchical structure dynamic interaction on the Internet to find a lot of tutorials dynamic form, the form is generated mostly at the beginning of loading. And my needs are required in the choice of the parent options under

Gangster reference Cultivation of the road and generate a form dynamically thanks ~

achieve

  1. preparation stage

    Known good configuration hierarchy

    const itemConfig = [{
            'key': 'tr069',
            'type': 'parent',// parent =>含有子级  item=>最底层级
            'item_type': 'select',// 本层级的类型 parent 默认为select 
            'children': [
                {
                    'key': 'url',
                    'type': 'item',
                    'item_type': 'input',
                    'value': ''
                },
                {
                    'key': 'username',
                    'type': 'item',
                    'item_type': 'input',
                    'value': ''
                },
                {
                    'key': 'password',
                    'type': 'item',
                    'item_type': 'input',
                    'value': ''
                },
                {
                    'key': 'data',
                    'type': 'item',
                    'item_type': 'object',
                    'value': {
                        'key': '',
                        'value': ''
                    }
                }
            ]
        },{
            'key': 'gateway',
            'type': 'parent',
            'item_type': 'select',
            'children': [
                {
                    'key': 'gw',
                    'type': 'item',
                    'item_type': 'input',
                    'value': ''
                }
            ]
    
        },{
            'key': 'optimy',
            'type': 'parent',
            'item_type': 'select',
            'children': [
                {
                    'key': 'enable',
                    'type': 'item',
                    'item_type': 'select',
                    'value': [true, false]
                }
            ]
    
        },
    ];
    

    Creating the initial level of the page

    Binding change event on the initial form Options

    <form autocomplete="off" [formGroup]="itemForm" fxLayout="column">
        <div fxLayout="row" fxLayoutAlign="center center">
            <mat-label>Group:</mat-label>
            <mat-form-field appearance="outline">
              <mat-select formControlName="group"                             (selectionChange)="changeSelect($event.value,'group')">
                <mat-option *ngFor="let item of itemConfig" [value]="item">
                  {{item.key}}
                </mat-option>
              </mat-select>
    
            </mat-form-field>
     </div>
    </form>
    

    The initial configuration options page form

    itemForm: FormGroup;
    
    // 根据父级的选择 展示的item列表
    itemPushDom = []; 
    
    ngOnInit(): void {
        this.itemForm = this.createFrom();
      }
    
      createFrom(): any {
        const group = this._formBuilder.group({
          'group': this._formBuilder.control('')
        });
        return group;
      }
    
  2. Dynamic insertion

    By now before operating on our pages you have the option to be able to see the initial

    Then there is the dynamic insertion, in fact, is simply divided into two steps: Dom insert options and add items FormGroup

    Clear previous selection plus the change after the parent

    Dom Insert Options

    You need to meet before the initial event delivery option is bound to change children's information

    The html also need to configure the relevant type may occur through ngSwtech display (small type in this case, only select and input type if more can refer to the official documentation of the dynamic form by controlling the type of component that appears)

    FormGroup Add Item

    Add and delete FormGroup form item by addControl () / removeControl () (you can also add validation)

    The following directly on the code

    component.html (paragraph form on the inside)

    <div fxLayout="row" fxLayoutAlign="center center" *ngFor="let newItem of itemPushDom">
            <mat-label >{{newItem.name}}:</mat-label>
            <mat-form-field appearance="outline" [ngSwitch]="newItem.type">
    
              <mat-select *ngSwitchCase="'select'" formControlName="{{newItem.name}}"
                (selectionChange)="changeSelect($event.value,newItem.name)" required>
                <mat-option *ngFor="let options of newItem.options" [value]="options.value">
                  {{options.key}}
                </mat-option>
              </mat-select>
    
              <input matInput *ngSwitchCase="'input'" formControlName="{{newItem.name}}" [value]="newItem.value" required>
    
            </mat-form-field>
    
     </div>
    

    component.ts

      changeSelect(item: any, itemName: string): void {
    
        // changeSelect 后检查是否需要删除原选项关联的item
        // 如果change的是父级的选项 递归删除已选
        this.checkItemDom(itemName);
    
        this.createItemDom(item, itemName);
    
      }
    
      createItemDom(item: any, itemName: string): void {
    
        // 动态添加FromControl
        this.addFromControl(item.key);
    
    
        const options = [];
    
        // 判断选择的item是否还有子级 (select)
        if (item.type === 'parent') { // 默认parent都是select
    
    
          // 查找子项点展示
          item.children.forEach(eleParent => {
            options.push({
              key: eleParent.key,
              value: eleParent
            });
          });
    
          this.addFromDom(item.key, itemName, item.item_type, '', options, item.type);
    
        } else if (item.type === 'item') {
    
          if (item.item_type === 'select') {
            item.value.forEach(eleItem => {
              options.push({
                key: eleItem,
                value: eleItem
              });
            });
    
            this.addFromDom(item.key, itemName, item.item_type, item.value, options, item.type);
    
          } else {  // 这里可以扩展多种类型 
    
            this.addFromDom(item.key, itemName, item.item_type, item.value, options, item.type);
    
          }
    
        }
      }
    
      // add/remove itemPushDom
      // 保存item的name/type/parent 在二维数组中保存子父级关联
    
      addFromDom(name: string, key: string, type: string, value: string, options: any, item_type: string): void {
    
        this.itemPushDom.push({
          parent: key,
          name: name,
          type: type,
          item: item_type,
          value: value,
          options: options
        });
      }
    
        checkItemDom(itemName: string): any {
    
        for (let i = 0; i < this.itemPushDom.length; i++) {
    
          if (this.itemPushDom[i].parent === itemName) {
    
            // 根据子父级关系 父级改变 查找相对应的子级删除 Dom和FormGroup
            this.checkItemDom(this.itemPushDom[i].name);
            this.delFromControl(this.itemPushDom[i].name);
            this.itemPushDom.splice(i, 1);
    
          }
        }
    
      }
    
    
    
      addFromControl(name: string): void {
    
        this.itemForm.addControl(name, this._formBuilder.control(''));
    
      }
    
      delFromControl(name: string): void {
    
        this.itemForm.removeControl(name);
    
      }
    

Finally, only through this.itemForm.value you can get the selected value

Or save itemPushDom

Guess you like

Origin www.cnblogs.com/nhxz001/p/12036553.html
Recommended