Angular 動態表單(根據選擇聯動顯示)


Angular 動態表單(根據選擇聯動顯示)

首先

記錄一下剛剛完成的一個功能

需求是根據固定的層級結構做動態聯動,在網上找了很多動態表單的相關教程,大部分都是在最開始加載就生成表單.而我的需求是需要在選擇了父級之后再展示父級下的選項

參考了大佬的修仙之路動態生成表單 感謝~

實現

  1. 准備階段

    配置好已知的層級結構

    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]
                }
            ]
    
        },
    ];
    

    頁面上創建初始層級

    在初始表單選項上綁定change事件

    <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>
    

    頁面配置表單的初始選項

    itemForm: FormGroup;
    
    // 根據父級的選擇 展示的item列表
    itemPushDom = []; 
    
    ngOnInit(): void {
        this.itemForm = this.createFrom();
      }
    
      createFrom(): any {
        const group = this._formBuilder.group({
          'group': this._formBuilder.control('')
        });
        return group;
      }
    
  2. 實現動態插入

    通過之前的操作 現在我們的頁面上已經能看到初始的選項了

    接下來就是實現動態插入 , 其實簡單來說就是分為兩個步驟: Dom插入可選項 和 FormGroup添加項

    再加上change父級之后清除之前的選擇

    Dom插入可選項

    需要配合之前初始選項綁定的change事件 傳遞children的信息

    html 上也需要配置好相關的可能出現的類型 通過ngSwtech 展示 (本例類型較少,只有select和input 如果類型較多可以參考官方文檔的動態表單 通過component控制出現的類型)

    FormGroup添加項

    通過 addControl()/removeControl() 對FormGroup 表單項 進行添加和刪除(也可以添加驗證)

    下面直接上代碼

    component.html (放在上一段form里)

    <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);
    
      }
    

最后只需要 通過 this.itemForm.value 就可以獲得所選的值

或者保存itemPushDom


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM