簡體   English   中英

角度反應表單:動態選擇下拉值不綁定

[英]Angular Reactive Forms: Dynamic Select dropdown value not binding

我有兩個數據數組: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/

演示中的問題

根據您提供的演示,有以下幾個問題:

  • 沒有分配formControlName來進行select
  • 您是綁定對象以選擇選項。

對於第一個問題

由於您循環通過associatedPrincipals動態顯示下拉列表。 associatedPrincipals是一個formArray ,可以考慮如下:

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

因此,您可以簡單地將在*ngFor expression中定義的i分配給formControlName

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

對於第二個問題

在將對象綁定到option ,Angular默認會將默認值和option的值與對象實例進行比較。

您可以設置相同的情況下(從價值得到referencePrincipals到formControl的formControls) associatedPrincipals (如@Fetra R.的答案)。 但這不是最方便的方法,因為你必須采取一些邏輯來保持對象的同一個實例。

在這里,我將為您提供另一種解決方案,該解決方案使用專門針對您當前情況設計的compareWith指令,請參閱docs

使用compareWith指令,您只需要實現一個compareFun來告訴angular如何將兩個對象(具有不同的實例)視為相同。這里可以包括同時comparing object instancecomparing object fields

<select formControlName="{{i}}" style="margin-top: 10px" [compareWith]="compareFun">
  <option value=null disabled selected hidden>--Select--</option>
  <option *ngFor="let refPrincipal of referencePrincipals.controls"
     [ngValue]="refPrincipal.value">{{ refPrincipal.value.code }}</option>
</select>

// tell angular how to compare two objects
compareFn(item1, item2): boolean {
  return item1 && item2 ? item1.code === item2.code : item1 === item2;
}

請參閱文檔和修復演示以了解有關它的詳細信息。

您需要將填充select的對象的完全相同的引用傳遞給所選的一個以獲取所選值。

在這里,您使用referencePrincipals的所有FormControl的值來填充您的選擇selectbox ,因此要選擇它,請使用此對象:

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

工作的plunker。 https://plnkr.co/edit/vw3WZ6?p=preview

您的方法至少有2個問題。

  1. 您的數據源可能是異步的。 這意味着你不應該在var responseData之后立即執行this.initiPrincipals(responseData[0]) ,而是在回調任何方法獲取數據或訂閱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)

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM