在Angular版本4中如何使用ngModel与Formarray选择对象

在Angular版本4中如何使用ngModel与Formarray选择对象

问题描述:

我已经成功设置了一个Formarray,它有两个控件。这些控件在HTML表单中设置为选择对象。我可以成功推送和显示多个元素集,但是当我尝试更改Formarray的第一个元素中的select对象的值时,其他Formarray元素选择对象的值相同。我正在使用[(ngModel)]将值绑定到对象,我相信这就是为什么值总是相同的原因。我尝试使用[(ngModel)] = stringArray [i]使用Fo​​rmarray索引的数组变量,但是当页面加载时出现错误。在Angular版本4中如何使用ngModel与Formarray选择对象

任何人都可以建议如何使用[(ngModel)]或其他机制来获取选择对象的值吗?我正在使用ng-lightning选择组件(版本1.3.0)和SLDS Lightning Design CSS。我正在使用Angular版本4.1.3。在我的应用程序的其他部分,我需要使用[(ngModel)]和一个字符串来获取选择对象的值。选择值是一个对象数组,而不是像字符串这样的基本变量。该组件没有定义onSelect()函数。

HTML:

<form [formGroup]="callFlowForm"> 
    <div formArrayName="callDevices"> 
    <!-- Check the correct way to iterate your form array --> 
    <div *ngFor="let callDevice of callFlowForm.controls.callDevices.controls; let i=index" [formGroupName]="i"> 
     <div class="form-group"> 
     <div class="slds-form-element slds-size--8-of-8"> 
      <ngl-form-element label="Device #: {{ i + 1 }}" class="slds-m-top--small"> 
      <select nglFormControl class="slds-select" 
        formControlName="callAsset" 
        [(ngModel)]="selectedDevice" 
        ngDefaultControl > 
       <option *ngFor="let device of devices" 
        [value]="device.id">{{device.assetName}} 
       </option> 
      </select> 
      </ngl-form-element> 
     </div> 
     </div> 
     <div class="form-group"> 
     <div class="slds-form-element slds-size--8-of-8"> 
      <ngl-form-element label="Protocol:" class="slds-m-top--small"> 
      <select nglFormControl class="slds-select" 
        formControlName="assetTransport" 
        [(ngModel)]="selectedTransport" 
        ngDefaultControl > 
       <option *ngFor="let protocol of transports" 
        [value]="protocol.id">{{protocol.type}} 
       </option> 
      </select> 
      </ngl-form-element> 
     </div> 
     </div> 
     <button *ngIf="callFlowForm.controls.callDevices.controls.length > 1" (click)="deleteDevice(i)" class="btn btn-danger">Delete Button</button> 
    </div> 
    </div> 
    <button type="button" (click)="addDevice()" class="btn btn-primary">Add Device</button> 
</form> 

组件:

selectedTransport: string; 
selectedDevice: string; 
public callFlowForm: FormGroup; 

transports: SipTransport[] = [{'id': 1, 'type': 'UDP'}, 
           {'id': 2, 'type': 'TCP'}, 
           {'id': 3, 'type': 'TLS'} 
          ]; 
devices: Asset[] = [{'id': 1, 'assetName': 'VCS', 'type': 'SIP Registrar'}, 
        {'id': 1, 'assetName': 'CUCM', 'type': 'Call Control'}, 
        {'id': 1, 'assetName': 'SBC', 'type': 'Call Control'}, 
        {'id': 1, 'assetName': 'EX60', 'type': 'Endpoint'} 
        ]; 

constructor(private dialService: DialService, 
    private formBuilder: FormBuilder 
) { } 

ngOnInit() { 
    this.selectedDevice = '1'; 
    this.selectedTransport = '1'; 
    this.callFlowForm = this.formBuilder.group({ 
     callDevices: this.formBuilder.array([this.addDevices()]) // here 
    }); 

} 

addDevices() { 
     return this.formBuilder.group({ 
      callAsset: [''], 
      assetTransport: [''] 
     }); 
} 

addDevice() { 
    const control = <FormArray>this.callFlowForm.controls['callDevices']; 
    control.push(this.addDevices()); 
} 

deleteDevice(index: number) { 
    const control = <FormArray>this.callFlowForm.controls['callDevices']; 
    control.removeAt(index); 
} 
+0

你是绝对正确的,这是因为ngModel的。双向结合在反应形式中极不鼓励。我无法理解为什么你需要双向绑定。为什么不使用formcontrol来代替。这就是应该使用:) – Alex

+0

嗨@ AJT_82,我不需要ngModel,但我已经在其他形式使用它,特别是在编辑形式,我想预先填充字段与当前值编辑。您的建议可以正常工作,因为我可以在不使用ngModel的情况下对所选的值进行console.log。我只需要弄清楚如何在提交时迭代组件中的formarray数据。我在控制台中得到了这个:这是我的表单{“callDevices”:[{“callAsset”:“24”,“assetTransport”:“2”},{“callAsset”:“34”,“assetTransport”:“1 “}]} –

+0

您也可以使用表单控件设置预选值,或者在设置值之前不建立表单。或者,当你收到它们时,通过修补值的形式,如果这是异步的。但关于你的问题...... *我只需要弄清楚如何在提交时迭代组件中的formarray数据*为什么你需要迭代它?我的意思是你想在迭代中完成什么?作为一个侧面说明它就像迭代任何数组:) – Alex

你为什么不这样做呢?

组件类:

selectedDevice: Asset; 

HTML代码:

  <select nglFormControl class="slds-select" 
       formControlName="callAsset" 
       [(ngModel)]="selectedDevice" 
       ngDefaultControl > 
      <option *ngFor="let device of devices" 
       [value]="device">{{device.assetName}} 
      </option> 
     </select>` 
+0

你的建议没有奏效。任何版本的ngModel似乎只将选择的对象绑定在一起。删除ngModel似乎是正确的路径,我只需要弄清楚如何迭代现在的formarray值。谢谢。 –

谢谢@ AJT_82谁帮我弄朝着正确的方向发展。这个问题可能不是最好的答案,因为你的答案是不要在formarray中使用ngModel。您需要通过表单控件设置和检索值。当互联网上的例子试图解释“模板驱动”与“模型驱动”或“反应性”形式之间的区别时,这使我感到困惑。他们似乎总是一样的。

这就是HTML应该是怎样的。

HTML:

<select nglFormControl class="slds-select" 
     formControlName="callAsset" 
     ngDefaultControl > 
     <option *ngFor="let device of devices" 
      [value]="device.id">{{device.assetName}} 
     </option> 
</select> 

在我的应用我使用数组值通过较大的集合搜索。当我想要得到的表单值我实现这个:

组件:

const formValue1 = this.callFlowForm.value; 

// this allows me to iterate through all devices in the formarray 
// and push those values into a list for sorting and further processing 
formValue1.callDevices.forEach((element: any) => { 
    allDevices.push(element.callDevice); 
}); 

不在此例,但在另一种形式,我需要设置窗体控件的值。我使用form.setValue({}),您需要设置所有表单控件的值。然后,如果您只需编辑一个值,则可以使用form.patchValue({})。另一种形式的一个例子是这样的。

的setValue:

this.dialForm.setValue({ 
    id: this.editDialplan.id, 
    number: this.editDialplan.number, 
    domainid: this.editDialplan.domainid.id 
}); 

patchValue:

this.dialForm.patchValue({ 
    number: this.editDialplan.number, 
});