角度反应表单:动态选择下拉值不绑定

时间:2017-09-11 21:36:04

标签: javascript angular angular-reactive-forms

我有两个数据数组:AssociatedPrincipals(以前保存的数据)和ReferencePrincipals(静态数据填充在下拉控件中)。我很难从AssociatedPrincipals中获取先前的值,以便在页面加载的动态数量(大多数示例使用单个下拉列表)下拉列表中显示/选择。

我不确定如何设置表单(代码隐藏和HTML),尤其是设置Select的formControlName。目前,每个下拉列表中的静态值都会填充,但我无法正确绑定选定值

public ngOnInit() {
    this.factsForm = this.formbuilder.group({
        associatedPrincipals: this.formbuilder.array([]),
        referencePrincipals: this.formbuilder.array([])
    });

    // Data for both of these methods comes from external source...
    var responseData = // HTTP source...
    // Push retrieved data into form
    this.initPrincipals(responseData[0]);
    // Push static data into form
   this.initStaticData(responseData[1]);
}

public initPrincipals(principals?: IAssociatedPrincipal[]): FormArray {
    principals.forEach((principal) => {
 this.associatedPrincipals.push(this.createPrincipalFormGroup(principal));
    });
}

public initStaticData(response: IReferencePrincipal[]) {
   response.forEach((principal) => {
      this.referencePrincipals.push(
           this.formbuilder.control({
                code: principal.code,
                canHaveLead: principal.canHaveLead,
                isDuplicate: false
              }));
        });
}

public createPrincipalFormGroup(principal: IAssociatedPrincipal) {
        return this.formbuilder.group({
            code: principal.code,
            canHaveLead: false,
            isDuplicate: false
        });
    }

public get associatedPrincipals(): FormArray {
        return this.factsForm.get('associatedPrincipals') as FormArray;
    }

    public get referencePrincipals(): FormArray {
        return this.factsForm.get("referencePrincipals") as FormArray;
    }

HTML:

 <form novalidate [formGroup]="factsForm">
        <div formArrayName="associatedPrincipals">
             <div *ngFor="let associatedPrincipal of associatedPrincipals.controls; let i=index;" [formGroupName]="i" >
                <select class="form-control create-input"
                        formControlName="i">
                     <option value=null disabled selected hidden>--Select--</option>
                       <option *ngFor="let refPrincipal of referencePrincipals.controls" [ngValue]="refPrincipal">refPrincipal.value.code</option>
                 </select>
             </div>
         </div>
    </form>

我感谢任何反馈!

编辑:已添加Plunker显示问题: https://embed.plnkr.co/XMLvFUbuc32EStLylDGO/

3 个答案:

答案 0 :(得分:8)

演示中的问题

根据您提供的演示,有以下几个问题:

  • formControlName没有分配select
  • 您正在绑定对象以选择该选项。

第一个问题

由于您循环遍历associatedPrincipals以动态显示下拉列表。 associatedPrincipals这是一个 formArray ,可以考虑如下:

associatedPrincipals = {
  "0": FormControl,
  "1": FormControl
}

因此,您只需将i表达式定义的*ngFor分配给formControlName

<select formControlName="{{i}}" style="margin-top: 10px">
   ...
</select>

对于第二个问题

对象绑定到option时,默认情况下,Angular会将默认值和option的值与对象实例进行比较。

您可以将同一个实例(从referencePrincipals的formControls的值获取)设置为associatedPrincipals的formControl(作为@Fetra R。的答案)。但这不是最方便的方法,因为你必须采取一些逻辑来保持对象的同一个实例。

在这里,我将为您提供另一种解决方案,该解决方案使用专为您当前情况设计的compareWith指令,请参阅 docs

使用compareWith指令,您只需要实现一个compareFun来告诉angular如何将两个对象(具有不同的实例)视为相同。这里可以包含comparing object instance和{ {1}}同时。

comparing object fields

参考 docs 并修复 demo 以了解相关详情。

答案 1 :(得分:2)

您需要将填充select的对象的完全相同的引用传递给选定的引用以获取所选值。

在这里,您使用FormControl中所有referencePrincipals的值来填充selectbox,因此要选择它,请使用此对象:

public createPrincipalFormControl(principal) {
    const selectedFormControl = this.referencePrincipals.controls.find(form => form.value.code === principal.code)
    return this.formbuilder.control(selectedFormControl.value);
}

工作人员。 https://plnkr.co/edit/vw3WZ6?p=preview

答案 2 :(得分:1)

您的方法至少有两个问题。

  1. 此处的数据源可能是异步的。这意味着您不应该在this.initiPrincipals(responseData[0])之后立即执行var responseData,而是在回调任何方法获取数据或订阅http服务时,如果您通过Observable获取数据。

    let subscription = myservice.getmedata.subscribe(data => { //here you should do your initializations with data from server };

    如果您的数据来自@Input(),那么右边的格式为ngOnChanges

  2. 正如Fetra指出的那样,无论您之前选择的选项与您预先填充到选择列表中的选项具有完全相同的值,为了将其设置为选中,您需要准确引用那些你填充它的人。所以,比如:

    this.formGroup.controls['yourSelectControl'].patchValue(this.yourInitialCollectionOfOptions.find(v => v.propertyByWhichYouWantToCompare == valueFromServer.propertyByWhichYouWantToCompare)

相关问题