Angular formControl - установить значение в определенной строке в цикле ngfor - PullRequest
1 голос
/ 14 апреля 2020

Пожалуйста, обратитесь к полному коду здесь в stackblitz

При изменении первого раскрывающегося списка столбцов на Модель наблюдается, что в 3-м столбце отображается список моделей.

нажмите кнопку добавления строки -> для второй строки, измените раскрывающийся список первого столбца на Система -> заметили, что раскрывающийся список третьего столбца для второй строки также изменился на список систем. Тем не менее, он также изменяет третий столбец других строк. Есть ли способ, которым я могу изменить только третий столбец второго ряда?

Таким образом, formControlName в ngFor l oop то же самое, и я хотел бы наблюдать за изменениями в formControl и обновлять выпадающие значения третьего столбца только для этой строки (не для всех строк)

При stackblitz

  • знаете ли вы, почему при выборе опции «содержит» во втором столбце в третьем столбце отображается объект «Объект». Предпочел бы пустое значение ввода.

  • Вы также знаете, как показать значение по умолчанию для поля ввода, то есть хотели бы показать первый элемент из каждого раскрывающегося списка при первой загрузке страницы / при добавлении новой строки .

    <form class="form" [formGroup]="form" noValidate>
      <div *ngFor="let row of rows" class="rows">
       <div>
            <select  formControlName="getType">
               <option *ngFor="let val of rootName"
                            [value]="val">
                        {{ val }}
                </option>
             </select>
        </div>
        <div>
             <select formControlName="typeValues">
               <option *ngFor="let val of type"
                  [value]="val">
                  {{ val }}
               </option>
             </select>
         </div>
         <div *ngIf="getValues.length>0" >
             <select formControlName="onValues">
                <option *ngFor="let val of getValues"
                        [value]="val">
                        {{ val }}
                </option>
              </select>
         </div>
         <div class="row-button">
             <button (click)="addRow()" [title]="'Add row'"> 
             </button>
         </div>
    
     rows = [0];
     this.form
        .get('typeValues')
        .valueChanges.pipe(takeUntil(this.ngUnsubscribe))
        .subscribe(val => {
            this.setValues();
        });
    
      this.form
          .get('getType')
          .valueChanges.pipe(takeUntil(this.ngUnsubscribe))
          .subscribe(val => {
              this.setValues();
          });
       }
    
     setValues() {
        const name = this.form.controls['getType'].value;
        const type = this.form.controls['tpeValues'].value;
        if (name != null && (type === 'is' || type === 'is not')) {
           if (name === 'Model') {
              this.getValues = this.getModelList;
           } else if (name === 'System'){
              this.getValues = this.getSystemList;
           }else if (name === 'OS'){
              this.getValues = this.getOSList;
           }
        } else {
           this.getValues = [];
        }
    }
    
    addRow() {
       this.formDirty = true;
       this.rows.push(this.rows.length);
    }
    

    '

1 Ответ

1 голос
/ 14 апреля 2020

Вам нужно использовать FormArray. Я полагаю, что вы хотите сделать что-то вроде

formArray:FormArray=new FormArray([this.newLine()]);

newLine() //This funcrion is WORNG, see update 2
{
   return this.formBuilder.group({
     onValues: [
        { value: "" },
        [Validators.required, Validators.pattern(/^[+-]?\d+(\.\d+)?$/)]
      ],
      ruleTypeValues: [{ value: "" }],
      getType: [{ value: "" }], 
      filterValue: [{ value: "" }]
   })
}
addLine()
{
   this.formArray.push(this.newLine())
}
removeLine(index)
{
   this.formArray.removeAt(index)
}

Для управления посмотрите на formArray.controls, используя [formGroup]

<form class="form" [formGroup]="formArray">
      <div *ngFor="let group of formArray.controls;let i=index" [formGroup]="group" class="rows">
        <div class="clr-select-wrapper">
          <select formControlName="getType">
            <ng-container *ngFor="let val of rootName">
              <option [ngValue]="val">{{ val }}</option>
            </ng-container>
          </select>
        </div>
        <div class="clr-select-wrapper">
          <select formControlName="ruleTypeValues">
            <ng-container *ngFor="let val of ruleType">
              <option [ngValue]="val">{{ val }}</option>
            </ng-container>
          </select>
        </div>
        <div class="clr-select-wrapper" *ngIf="getValues.length > 0">
          <select formControlName="onValues">
            <ng-container *ngFor="let val of getValues">
              <option [ngValue]="val">{{ val }}</option>
            </ng-container>
          </select>
        </div>
        <input
          *ngIf="getValues.length === 0"
          type="text"
          formControlName="filterValue"
          class="text"
          placeholder="sdf"
        />
        <div class="row-button">
          <button  (click)="addLine()">Add row</button>
          <button  (click)="removeLine(i)">Remove row </button>
          <button (click)="addBlock(row)">Add block</button>
        </div>
      </div>
    </form>

Обновление , чтобы подписаться на valueChanges Для formGroup нам нужно изменить функцию newLine и сделать ее в два этапа:

newLine()
{
   const group=this.formBuilder.group({
     onValues: [
        { value: "" },
        [Validators.required, Validators.pattern(/^[+-]?\d+(\.\d+)?$/)]
      ],
      ruleTypeValues: [{ value: "" }],
      getType: [{ value: "" }], 
      filterValue: [{ value: "" }]
   })
   group.valuesChange.subscribe((res:any)=>{
     ..here the code
   }
   //or, if we only want to check, e.g. "getType"
   group.get('getType').valueChange.subscribe((res:any)=>{
      ..here the code
   }
   return group;
}

ИЛИ, после создания формы, например, в ngOnInit

ngOnInit()
{
    this.formArray.valueChanges.subcribe((res:any)=>{
       ..here the code..
    }
}

Update2 функция newLine неверна !!!

должно быть похоже на

newLine(){
   const group=this.formBuilder.group({
     onValues: ["",
        [Validators.required, Validators.pattern(/^[+-]?\d+(\.\d+)?$/)]
      ],
      ruleTypeValues: [""],
      getType: [""], 
      filterValue: [""]
   })
   return group
}
...