typescript Angular 6 Reactive Forms - 按条件动态设置 <select> FormControl 的选定 <option>
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/52387269/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
Angular 6 Reactive Forms - Set the selected <option> of a <select> FormControl dynamically by condition
提问by PHilgarth
I need to know how I set the selected <option>
of a <select>
FormControl dynamically by condition.
我需要知道如何按条件动态设置FormControl的选定<option>
项<select>
。
Let's say we have customers with orders. There is a dropdown menu where we select a customer and depending on that customer the options for the orders dropdown menu should be set dynamically and a specific order should be selected.
假设我们有客户有订单。有一个下拉菜单,我们可以在其中选择一个客户,根据该客户,应该动态设置订单下拉菜单的选项并选择一个特定的订单。
Also both dropdown menus have an <option>
“(new customer/order)” in case there is not yet a customer or an order, so if we route to that form without having a customer, this “new” option should be selected in both drop down menus. If we have a customer without orders, the “new” option should be selected in the orders dropdown menu.
此外,两个下拉菜单都有一个<option>
“(新客户/订单)”,以防还没有客户或订单,因此如果我们在没有客户的情况下路由到该表单,则应在两个下拉菜单中选择此“新”选项菜单。如果我们的客户没有订单,则应在订单下拉菜单中选择“新建”选项。
This is the form.component.html:
这是 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>
This is the form.component.ts:
这是 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;
}
Currently I'm routing to the form and provide an id with the url. The customer dropdown menu selects the correct customer depending on the id in the url.
目前我正在路由到表单并提供一个带有 url 的 id。客户下拉菜单根据 url 中的 id 选择正确的客户。
However, the order dropdown menu is only populated correctly, but the selection does not work. No option at all is selected.
但是,订单下拉菜单仅正确填充,但选择不起作用。根本没有选择任何选项。
If I replace the value in this statement:
如果我替换此语句中的值:
this.customerForm.patchValue({ orders: this.filteredOrders[0].id }
this.customerForm.patchValue({ orders: this.filteredOrders[0].id }
with the "(new order)"
string already specified in the html:
使用"(new order)"
已在 html 中指定的字符串:
this.customerForm.patchValue({ order: "(new order)" })
this.customerForm.patchValue({ order: "(new order)" })
it works. The string "(new order)"
is selected in the orders dropdown menu. It just don't work for the filteredOrders.
有用。该字符串"(new order)"
是在订单下拉菜单中选择的。它只是不适用于filteredOrders。
What am I doing wrong here? Do I maybe need a whole different approach here?
我在这里做错了什么?我可能需要一种完全不同的方法吗?
回答by PHilgarth
Okay, after a couple of hours I got it. Here are my updated .html and .ts files for your interest:
好的,几个小时后我得到了它。以下是我更新的 .html 和 .ts 文件,供您参考:
HTML:
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
.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);
}
}
As you can see, in the HTML i now use "[value]" instead of "[ngValue]" and "customer.name" / "order.id" instead of only "customer" / "order".
如您所见,在 HTML 中,我现在使用“[value]”而不是“[ngValue]”和“customer.name”/“order.id”,而不是仅使用“customer”/“order”。
In the .ts-file I got rid of the "patchValue()" method and brought in the "setValue" method.
在 .ts 文件中,我去掉了“patchValue()”方法并引入了“setValue”方法。
Here is the working stackblitz-example:
这是有效的 stackblitz 示例:
https://stackblitz.com/edit/angular-conditionaldropdown-gnajge
https://stackblitz.com/edit/angular-conditionaldropdown-gnajge
回答by RoadEx
I think that the problem comes from the object that is selected in the order selector (also in the customers one, in fact).
我认为问题来自在订单选择器中选择的对象(实际上也是在客户中)。
<option [ngValue]="order" *ngFor="let order of filteredOrders">
{{order.id}}
</option>
This means that the whole order
object will be selected and not only the order id. In this case, if you try to patch the value only with the order.id
, then it won't work : the selector wait for an Order
object, not the order.id
.
这意味着order
将选择整个对象,而不仅仅是订单 ID。在这种情况下,如果您尝试仅使用 修补值order.id
,那么它将不起作用:选择器等待Order
对象,而不是order.id
。
I put together a quick stackblitz with a working version of the code you put in the question: https://stackblitz.com/edit/angular-drop-dowb. The only real difference is that
我将一个快速的 stackblitz 与您在问题中提供的代码的工作版本放在一起:https://stackblitz.com/edit/angular-drop-dowb 。唯一真正的区别是
this.customerForm.patchValue({
orders: this.filteredOrders[0]
});
is used instead of
被用来代替
this.customerForm.patchValue({
orders: this.filteredOrders[0].id }
});
Update
更新
So, i've updated the stackblitz.
所以,我更新了stackblitz。
To keep the orders
field with the correct values along the customer
, you'll need to add a (change)
in the select
field.
要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>
Don't forget to pass the customer id
field as the value instead of the customer
- Angular does not seem to like it. With the id
value then, you'll need to add a updateOrders
function in the component.ts
.
不要忘记传递 customerid
字段作为值而不是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]);
}
In the case the id
is not in the customers list, then you'll only update the orders
with a null
value, corresponding to tyour (new order)
. And if the id
is in the customers list, then you'll update the filteredOrders
.
如果id
不在客户列表中,那么您将只使用orders
与null
tyour 相对应的值更新(new order)
。如果id
是在客户列表中,那么您将更新filteredOrders
.