简体   繁体   English

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

[英]In Angular version 4 how can I use ngModel with Formarray select objects

I have successfully set up a Formarray that has two controls. 我已经成功建立了一个有两个控件的Formarray。 The controls are set in the HTML form as select objects. 控件在HTML表单中设置为选择对象。 I can successfully push and display multiple element sets but when I try to change the value of the select object in the first element of the Formarray the other Formarray element select objects take on the same value. 我可以成功地推送和显示多个元素集,但是当我尝试在Formarray的第一个元素中更改select对象的值时,其他Formarray元素选择对象采用相同的值。 I am using [(ngModel)] to bind a value to the object and I believe that is why the vales are always the same. 我正在使用[(ngModel)]将值绑定到对象,我相信这就是为什么vales总是相同的。 I tried using an array variable with [(ngModel)]=stringArray[i] using the Formarray index, but I get errors when the page is loaded. 我尝试使用带有[(ngModel)] = stringArray [i]的数组变量使用Formarray索引,但是在加载页面时出现错误。

Can anyone suggest how to get the value of the select object using [(ngModel)] or other mechanism? 任何人都可以建议如何使用[(ngModel)]或其他机制获取选择对象的值? I am using an ng-lightning select component (version 1.3.0) and SLDS Lightning Design CSS. 我正在使用ng-lightning选择组件(版本1.3.0)和SLDS Lightning Design CSS。 I am using Angular version 4.1.3. 我使用的是Angular 4.1.3版。 In other parts of my app, I need to use [(ngModel)] with a string in order to get the value of a select object. 在我的应用程序的其他部分,我需要使用[(ngModel)]与字符串,以获取选择对象的值。 The select values are an array of objects and not a primitive variable like a string. 选择值是一个对象数组,而不是像字符串一样的基本变量。 The component does not have an onSelect() function defined. 该组件没有定义onSelect()函数。

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

Component: 零件:

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

Why don't you do this? 你为什么不这样做?

Component class: 组件类:

selectedDevice: Asset;

HTML code: HTML代码:

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

Thank you to @AJT_82 who helped get me going in the right direction. 感谢@ AJT_82,他帮助我朝着正确的方向前进。 The question may not have been worded the best as the answer is you DON'T use ngModel in a formarray. 这个问题可能没有措辞得最好,因为答案是你不要在formarray中使用ngModel。 You need to set and retrieve the values via the form controls. 您需要通过表单控件设置和检索值。 This has confused me when the examples on the Internet try to explain the difference between "template driven" versus "model driven" or "reactive" forms. 当互联网上的例子试图解释“模板驱动”与“模型驱动”或“反应”形式之间的区别时,这让我很困惑。 They always seemed to be just the same. 他们似乎总是一样的。

This is how the HTML should be. 这就是HTML应该如何。

HTML: HTML:

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

In my app I am using the array values to search through a larger collection. 在我的应用程序中,我使用数组值来搜索更大的集合。 When I want to get the values of the form I implement this: 当我想获取表单的值时,我实现了这个:

Component: 零件:

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

Not in this example, but in another form I needed to set the values of the form controls. 不在此示例中,但在另一种形式中,我需要设置表单控件的值。 I used form.setValue({}) where you need to set the value of all the form controls. 我使用了form.setValue({}),你需要设置所有表单控件的值。 Then if you need to just edit a single value then you use form.patchValue({}). 然后,如果您只需编辑单个值,则使用form.patchValue({})。 An example of a set in that other form is this. 其他形式的集合的示例是这样的。

setValue: 设定值:

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

patchValue: patchValue:

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

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM