選択した_<option>
_ FormControlの_<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>
_
これは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のIDを提供しています。顧客のドロップダウンメニューは、URLのIDに応じて正しい顧客を選択します。
ただし、注文ドロップダウンメニューは正しく設定されているだけで、選択は機能しません。オプションがまったく選択されていません。
このステートメントの値を置き換える場合:
_this.customerForm.patchValue({ orders: this.filteredOrders[0].id }
_
"(new order)"
文字列がHTMLで既に指定されている場合:
this.customerForm.patchValue({ order: "(new order)" })
できます。文字列"(new order)"
が注文ドロップダウンメニューで選択されています。 FilteredOrdersでは機能しません。
ここで何が悪いのですか?ここでまったく異なるアプローチが必要ですか?
さて、数時間後に私はそれを得ました。ここにあなたの興味のために私の更新された.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ファイル
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では「[ngValue]」の代わりに「[value]」を使用し、「customer」/「order」だけではなく「customer.name」/「order.id」を使用しています。
.tsファイルで、「patchValue()」メソッドを削除し、「setValue」メソッドを導入しました。
これが実際のstackblitzの例です:
https://stackblitz.com/edit/angular-conditionaldropdown-gnajge
問題は、注文セレクターで選択されたオブジェクト(実際には顧客のものでもある)に起因すると思います。
<option [ngValue]="order" *ngFor="let order of filteredOrders">
{{order.id}}
</option>
つまり、注文IDだけでなく、order
オブジェクト全体が選択されます。この場合、order.id
のみを使用して値にパッチを適用しようとしても、機能しません。セレクタは、order.id
ではなくOrder
オブジェクトを待機します。
私はあなたが質問に入れたコードの作業バージョンと一緒に簡単なstackblitzを組み立てます: https://stackblitz.com/edit/angular-drop-dowb 。唯一の本当の違いは
this.customerForm.patchValue({
orders: this.filteredOrders[0]
});
の代わりに使用されます
this.customerForm.patchValue({
orders: this.filteredOrders[0].id }
});
だから、私はstackblitzを更新しました。
orders
フィールドをcustomer
に沿って正しい値で維持するには、select
フィールドに(change)
を追加する必要があります。
<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
valueの場合、component.ts
にupdateOrders
関数を追加する必要があります。
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
は(new order)
に対応するnull
値でのみ更新します。また、id
が顧客リストにある場合は、filteredOrders
を更新します。