Angular 6 Reactive Forms - динамически устанавливает выбранный <option>из <select>FormControl по условию - PullRequest
0 голосов
/ 18 сентября 2018

Мне нужно знать, как я динамически устанавливаю <option> формы FormControl *1001* по условию.

Допустим, у нас есть клиенты с заказами.Существует раскрывающееся меню, в котором мы выбираем клиента, и в зависимости от этого клиента параметры для раскрывающегося меню заказов должны устанавливаться динамически, и должен быть выбран конкретный заказ.

Также оба раскрывающихся меню имеют <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>

Это форма.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;
}

В настоящее время я направляюсь в форму и предоставляю идентификатор с URL.Раскрывающееся меню клиента выбирает правильного клиента в зависимости от идентификатора в URL.

Однако раскрывающееся меню заказа заполнено только правильно, но выбор не работает.Опции вообще не выбраны.

Если я заменим значение в этом операторе:

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

на строку "(new order)", уже указанную в html:

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

все работает.Строка "(new order)" выбирается в раскрывающемся меню заказов.Это просто не работает для фильтрованных заказов.

Что я здесь не так делаю?Может быть, мне нужен совершенно другой подход?

Ответы [ 2 ]

0 голосов
/ 20 сентября 2018

Хорошо, через пару часов я понял.Вот мои обновленные файлы .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>

.ts-file

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

Как видите, вHTML теперь я использую «[value]» вместо «[ngValue]» и «customer.name» / «order.id» вместо только «customer» / «order».

В .ts-файл Я избавился от метода «patchValue ()» и ввел метод «setValue».

Вот пример работы stackblitz:

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

0 голосов
/ 18 сентября 2018

Я думаю, что проблема возникает из-за объекта, который выбран в селекторе заказов (в том числе и в клиентском).

<option [ngValue]="order" *ngFor="let order of filteredOrders">
    {{order.id}}
</option>

Это означает, что весь объект order будетвыбран и не только идентификатор заказа.В этом случае, если вы попытаетесь исправить значение только с помощью order.id, оно не будет работать: селектор ожидает объект Order, а не order.id.

Я собрал быстрый стек с работающей версией кода, который вы задали в вопросе: https://stackblitz.com/edit/angular-drop-dowb. Единственное реальное отличие состоит в том, что вместо 1011 *

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

используется

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

Обновление

Итак, я обновил стек стека.

Чтобы в поле orders были правильные значения вдоль customer, вы 'Вам нужно будет добавить (change) в поле select.

<select formControlName="customers" (change)="updateOrders($event)">
    <option [ngValue]="null">(new customer)</option>
    <option [value]="customer.id" *ngFor="let customer of customers" >
        {{customer.name}}
    </option>
</select>

Не забудьте передать поле id клиента в качестве значения вместо customer - Angular, похоже, не нравится.При значении id вам нужно добавить функцию updateOrders в component.ts.

  updateOrders(event) {
    const index = this.customers.findIndex(item => item.id == event.target.value);
    if (index === -1) {
      this.customerForm.controls.orders.setValue(null);
      return;
    }
    this.filteredOrders = this.getCustomersOrders(this.customers[index]);
    this.customerForm.controls.orders.setValue(this.filteredOrders[0]);
  }

В случае, если id отсутствует в списке клиентов, тогда выОбновим orders только значением null, соответствующим значению (new order).И если id находится в списке клиентов, то вы обновите filteredOrders.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...