【问题标题】:Why can't I use a select elements with object based options within reactive forms? What am I doing wrong?为什么我不能在反应式表单中使用带有基于对象的选项的选择元素?我究竟做错了什么?
【发布时间】:2019-08-12 20:49:54
【问题描述】:

我有一个反应式表单,其中包括一个父表单(国家/地区)和一个子表单数组(statesForm),其中的 select 元素具有基于对象的选项。我正在使用 [ngValue] 将选择元素的值设置为对象。使用选择列表的“(更改)”事件时,我无法从表单控件中检索所选值。

我已经从一个更复杂的页面中删减了这个示例。因此,我知道可能还有其他方法可以完成,但我有兴趣具体弄清楚为什么我不能让基于对象的选择选项与此设置一起使用。

这里是演示该问题的 stackblitz 的链接: https://stackblitz.com/edit/angular-jigxyl

这里是stackblitz代码的相关部分

ngOnInit(): void {
        this.getCountry().subscribe(
            country => {
                this.country = country;
                this.countryForm = this.buildFormGroup();
            },
            (error: any) => {
                console.log(error);
            }
        );
    }

    CityCompare(c1: City, c2: City): boolean {
        return c1 && c2 ? c1.name === c2.name : c1 === c2;
    }

    onSelectedStateChange(index: any): void {
        var rowsFormArray = <FormArray>this.countryForm.controls["statesForm"];
        var formGroup = <FormGroup>rowsFormArray.controls[index];

        this.selectedCity = formGroup.controls["selectedCity"].value;
        console.log(this.selectedCity);
    }

    private buildFormGroup(): FormGroup {
        var formArray = new FormArray([]);

        for (let i = 0; i < this.country.states.length; i++) {
            var state = this.country.states[i];

            var formGroup = new FormGroup({});

            var formControl = new FormControl(state.selectedCity, [Validators.required]);
            formGroup.addControl("selectedCity", formControl);

            formArray.push(formGroup);
        }

        return new FormGroup({
            statesForm: formArray
        });
    }
<form [formGroup]="countryForm">
    <div>
      <p>
      I am using reactive forms and trying to use objects to set the options list
      of a select element
      <br/>
      This form containts a form array as well. 
      <br/>
      No matter which option I choose, the form control always evaluates to the first options<br/>
      --------------------------------------
      </p>
    </div>
    <div>
        Country:{{country?.name}}
    </div>
    <div formArrayName="statesForm">
        <div *ngFor="let state of country?.states; let $index = index">
            <div>State: {{state.abbreviation}}</div>
            <div [formGroupName]="$index">
                <select
                    class="form-control input-sm"
                    formControlName="selectedCity"
                    [compareWith]="CityCompare"
                    (change)="onSelectedStateChange($index)"
                >
                    <option *ngFor="let city of state?.cities" [ngValue]="state?.selectedCity">
                        {{ city?.name }}
                    </option>
                </select>
            </div>
        </div>
    </div>

    Chosen object:{{this.selectedCity | json}}
</form>

【问题讨论】:

  • 除了stackblitz之外,您还需要将实际代码放入问题中

标签: angular angular-reactive-forms


【解决方案1】:

您只需将ngValue设置为城市对象,选择的值已经设置您可以检查

   <div formArrayName="statesForm">
        <div *ngFor="let state of country?.states; let $index = index">
            <div>State: {{state.abbreviation}}</div>
            <div [formGroupName]="$index">
                <select
                    class="form-control input-sm"
                    formControlName="selectedCity"
                    [compareWith]="CityCompare"
                    (change)="onSelectedStateChange($index)">
                    <option *ngFor="let city of state?.cities" [ngValue]="city">
                        {{ city?.name }}
                    </option>
                </select>
            </div>
        </div>
    </div>

demo ??

您无需跟踪表单已同步的选定值 使用 ui,因此任何更改都将反映到 formGroup

getSelectedStateValue(index) {
  return (this.countryForm.get('statesForm') as FormArray).controls[index].value
}

模板

Chosen object:{{getSelectedStateValue($index) | json}}

【讨论】:

  • 太棒了!谢谢你!我看不到这个问题。感谢您指出这一点并成为第二双眼睛!
【解决方案2】:

(change) 事件是一个模板驱动的表单方法,你想在使用响应式表单时订阅表单控件上的 valueChanges:

 this.countryForm.get('statesForm').valueChanges.subscribe(v => 
              this.onSelectedStateChange(v[0]));

闪电战:https://stackblitz.com/edit/angular-pxxuxy?file=src/app/app.component.ts

这种情况有点奇怪,因为您有一个带有控件数组的组,但只有一个选定的城市,而看起来可能有多个。

您还出于某种原因将每个选项的值设置为州所选城市,您需要将选项值设置为每个城市:

[ngValue]="city"

【讨论】:

  • 如果有多个州,比如有多个国家,valueChanges 将在每次数组难以确定所选值时发出,除非他进行一些更改以将旧的所选值与新的,??
  • @malbarmawi 会是,但如果他的目标是在选择表单列表中找到最近选择的城市,这也是一个非常奇怪的用例。
猜你喜欢
  • 1970-01-01
  • 2012-04-07
  • 2013-08-06
  • 1970-01-01
  • 2016-07-18
  • 2016-05-27
  • 2020-09-21
  • 2023-03-25
  • 1970-01-01
相关资源
最近更新 更多