Angular 6 Reactive Forms - 按条件动态设置 <select> FormControl 的选定 <option>

PHi*_*rth 8 typescript angular-reactive-forms angular6

我需要知道如何按条件动态设置FormControl的选定<option><select>

假设我们有客户有订单。有一个下拉菜单,我们可以在其中选择客户,并根据该客户动态设置订单下拉菜单的选项并选择特定订单。

此外,两个下拉菜单都有一个<option>“(新客户/订单)”,以防还没有客户或订单,因此如果我们在没有客户的情况下路由到该表单,则应在两个下拉菜单中选择此“新”选项菜单。如果我们的客户没有订单,则应在订单下拉菜单中选择“新建”选项。

这是 form.component.html:

<form [formGroup]="customerForm">
    <select formControlName="customers">
        <option>(new customer)</option>
        <option [ngValue]="customer" *ngFor="let customer of customers">
            {{customer.name}}
        </option>
    </select>
    <select formControlName="orders">
        <option>(new order)</option>
        <option [ngValue]="order" *ngFor="let order of filteredOrders">
            {{order.id}}
        </option>
    </select>
</form>
Run Code Online (Sandbox Code Playgroud)

这是 form.component.ts:

customerForm: FormGroup;

customers: Customer[] = [
{   "id": 1,
    "name": "Meghan Castellano",
    "orderIds": [1,2] },
{   "id": 2,
    "name": "Monika Weiss",
    "orderIds": [3,4] }];

orders: Order[] = [{"id": 1},{"id": 2},{"id": 3},{"id": 4}];

filteredOrders: Order[];

constructor( private route: ActivatedRoute,
            private fb: FormBuilder) {}

ngOnInit() {
    this.customerForm = this.fb.group({
        customers: '',
        orders: '' });

    let customerId = this.route.snapshot.getParam('id');

    if (customerId == 0) {
        this.customerForm.patchValue({
            customers: "(new customer)",
            orders: "(new order)" });
    }
    else
    {
        let customer = this.customers[customerId];

        this.customerForm.patchValue({ customers: customer.name });

        if (customer.orderIds.length != 0) {
            this.filteredOrders = getCustomersOrders(customer);

        this.customerForm.patchValue({
            orders: this.filteredOrders[0].id }
        }
    }
}

getCustomersOrders(customer: Customer): Order[] {
    let orders: Order[];

    for (var id = 0; id < customer.orderIds.length; id++) {
        let orderId = customer.orderIds[id];
        let order = this.orders.find(i => i.id == orderId);
        orders.push(order); }

    return orders;
}
Run Code Online (Sandbox Code Playgroud)

目前我正在路由到表单并提供一个带有 url 的 id。客户下拉菜单根据 url 中的 id 选择正确的客户。

但是,订单下拉菜单仅正确填充,但选择不起作用。根本没有选择任何选项。

如果我替换此语句中的值:

this.customerForm.patchValue({ orders: this.filteredOrders[0].id }

使用"(new order)"已在 html 中指定的字符串:

this.customerForm.patchValue({ order: "(new order)" })

有用。该字符串"(new order)"是在订单下拉菜单中选择的。它只是不适用于filteredOrders。

我在这里做错了什么?我可能需要一种完全不同的方法吗?

PHi*_*rth 9

好的,几个小时后我得到了它。以下是我更新的 .html 和 .ts 文件,供您参考:

HTML:

<form class="form-container" [formGroup]="customerForm">
    <select formControlName="customer" (change)="onCustomerChanged($event)">
        <option>(new customer)</option>
        <option *ngFor="let customer of customers" [value]="customer.name">
            {{customer.name}}
        </option>
    </select>
    <select formControlName="order">
        <option>(new order)</option>
        <option *ngFor="let order of filteredOrders" [value]="order.id">
            {{order.id}}</option>
    </select>
</form>
Run Code Online (Sandbox Code Playgroud)

.ts 文件

export class CustomerFormComponent implements OnInit {

  customerForm: FormGroup;
  selectedCustomer: Customer;
  filteredOrders: Order[];

  customers: Customer[] = [...];
  orders: Order[] = [...];  

  constructor(private route: ActivatedRoute,
              private fb: FormBuilder) { }

  ngOnInit() {
    this.customerForm = this.fb.group({
      customer: "",
      order: ""
    });

    let customerId = Number(this.route.snapshot.paramMap.get('customerId'));
    this.setFormControlValues(customerId);
  }

  setFormControlValues(customerId: number) {
    if (customerId == 0) {
      this.customerForm.get('customer').setValue("(new customer)");
      this.customerForm.get('order').setValue("(new order)");
    }
    else  {
      this.selectedCustomer = this.customers.find(i => i.id == customerId);
      this.filteredOrders = this.getCustomerOrders(this.selectedCustomer);

      this.customerForm.get('customer').setValue(this.selectedCustomer.name);
      this.customerForm.get('order').setValue(this.filteredOrders[0].orderNumber);
    }
  }

  getCustomerOrders(customer: Customer) : Order[] {
    let orders: Order[] = [];

    for (var id = 0; id < customer.orderIds.length; id++)  {
      let orderId = customer.orderIds[id];
      orders.push(this.orders.find(i => i.id == orderId));
    }

    return orders;
  }

  onCustomerChanged(event: any) {
    this.selectedCustomer = this.customers.find(n => n.name == event.target.value);

    this.setFormControlValues(this.selectedCustomer.id);
  }
}
Run Code Online (Sandbox Code Playgroud)

如您所见,在 HTML 中,我现在使用“[value]”而不是“[ngValue]”和“customer.name”/“order.id”,而不是仅使用“customer”/“order”。

在 .ts 文件中,我去掉了“patchValue()”方法并引入了“setValue”方法。

这是有效的 stackblitz 示例:

https://stackblitz.com/edit/angular-conditionaldropdown-gnajge