Angular Mat-Autocomplete 在 POST 请求中发送整个对象

huangapple go评论71阅读模式
英文:

Angular Mat-Autocomplete Sending Entire Object on Post Request

问题

我有一个自动完成字段,前端表现正确,但由于[value]="option",它会将整个对象发送到后端。当我将它更改为[value]="option.id"时,表单可以正确提交,但一旦选择了选项,[displayWith]函数就会中断。输入为空,因为displayWith函数使用对象来更新输入。

我该如何修改以向后端发送正确的ID,同时保留显示函数?我尝试通过displayWith将expenseCategory作为参数发送,但它不在for循环中,因此我无法访问选项对象。需要注意的是,这些是作为formArray的一部分动态创建的输入字段。

这是自动完成字段:

<mat-form-field appearance="outline" class="full-width-input">
  <mat-label>费用类别</mat-label>
  <input type="text" aria-label="Assignee" matInput formControlName = "expense_category_id" [matAutocomplete]="auto">
  <mat-autocomplete #auto="matAutocomplete" [displayWith]="displayExpenseCategoryFn">
    <mat-option *ngFor="let option of filteredExpenseCategories[i] | async" [value]="option">
      {{option.category}}
    </mat-option>
  </mat-autocomplete>
</mat-form-field>

这是displayWith函数:

displayExpenseCategoryFn(expenseCategory?: ExpenseCategory): string | undefined {
  return expenseCategory ? expenseCategory.category : undefined;
}
英文:

I have an autocomplete field that behaves correctly on the frontend, but it's sending the entire object to the backend due to [value]="option". When I change it to [value]="option.id" the form submits correctly, however this breaks the [displayWith] function once an option is selected. The input is blank due to the fact displayWith uses the object to update the input.

What Can I modify to send the correct id to the backend while preserving the display function? I tried sending the expenseCategory through displayWith as a parameter, but it's not in the for block, therefore I don't have access to the option object. One thing to note, these are dynamically created inputs as part of a formArray.

Heres the autocomplete field:

<mat-form-field appearance="outline" class="full-width-input">
  <mat-label>Expense Category</mat-label>
  <input type="text" aria-label="Assignee" matInput formControlName = "expense_category_id" [matAutocomplete]="auto">
  <mat-autocomplete #auto="matAutocomplete" [displayWith]="displayExpenseCategoryFn">
    <mat-option *ngFor="let option of filteredExpenseCategories[i] | async" [value]="option">
      {{option.category}}
    </mat-option>
  </mat-autocomplete>
</mat-form-field>

Here's the displayWith function:

displayExpenseCategoryFn(expenseCategory?: ExpenseCategory): string | undefined {
  return expenseCategory ? expenseCategory.category : undefined;
}

答案1

得分: 0

以下是翻译好的内容:

首先,我确定这是一个拼写错误,但在以下代码中的 "i" 是指什么:

let option of filteredExpenseCategories[i]

其次,如果您已经定义了模板,就不需要使用 displayWith 函数,因为您在绑定 {{option.category}} 中已经定义了模板。

所以,您可以简单地回到 [value]="option.id",这是我认为最简单的方式。

如果您正在通过代码提交表单,那么在数据传送到后端之前,您可以对数据进行处理。

您还可以利用 MatAutoComplete 的 (optionSelected) 事件(https://material.angular.io/components/autocomplete/api):

public selectOption(e: MatAutocompleteSelectedEvent): void {
  const myRealObject = e.option.value as MyRealObject;
  // 在这里执行其他需要的操作,如调整数据或清除自动完成控件中的输入
}
<mat-autocomplete #myAutoComplete (optionSelected)="selectOption($event)">
  <mat-option *ngFor="let option of options" [value]="option.id">
    {{option.name}}
  </mat-option>
</mat-autocomplete>

希望这能帮助您。

英文:

First, I'm sure this is a typo, but what is i, in:

<!-- begin snippet: js hide: false console: true babel: false -->

<!-- language: lang-js -->

let option of filteredExpenseCategories[i]

<!-- end snippet -->

Secondly, you don't need a displayWith function if you also are defining a template, which you are with the binding {{option.category}}.

So you could just go back to [value]="option.id", which is the easiest way IMHO.

If you are submitting your form via code, then you can always massage the data before it goes off to the gods.

You could also make use of the (optionSelected) event of the MatAutoComplete (https://material.angular.io/components/autocomplete/api):

<!-- begin snippet: js hide: false console: true babel: false -->

<!-- language: lang-js -->

public selectOption(e: MatAutocompleteSelectedEvent): void {
  const myRealObject = e.option.value as MyRealObject;
  // do anything else you need here, such as tweak the data or clearout the typeahead control
}

<!-- language: lang-html -->

&lt;mat-autocomplete #myAutoComplete (optionSelected)=&quot;selectOption($event)&quot;&gt;
  &lt;mat-option *ngFor=&quot;let option of options&quot; [value]=&quot;option.id&quot;&gt;
    {{option.name}}
  &lt;/mat-option&gt;
&lt;/mat-autocomplete&gt;

<!-- end snippet -->

Hope this helps.

答案2

得分: 0

好的,以下是您要翻译的内容:

So what I did was bind displayExpenseCategoryFn to the controller, so I could search through the expenseCategories array to extract the category name and display that in the input field.

我所做的是将 displayExpenseCategoryFn 绑定到控制器,以便我可以搜索 expenseCategories 数组以提取类别名称并在输入字段中显示它。

&lt;mat-autocomplete #auto=&quot;matAutocomplete&quot; [displayWith]=&quot;displayExpenseCategoryFn.bind(this)&quot;&gt;
    &lt;mat-option *ngFor=&quot;let option of filteredExpenseCategories[i] | async&quot; [value]=&quot;option.id&quot;&gt;
        {{option.category}}
    &lt;/mat-option&gt;
&lt;/mat-autocomplete&gt;

I then made the following changes to the displayWith function.

然后,我对 displayWith 函数进行了以下更改。

displayExpenseCategoryFn(expenseCategoryId?: number): string | undefined {
    const index = this.expenseCategories.findIndex(expenseCategoryIndex =&gt; expenseCategoryIndex.id === expenseCategoryId);
    return expenseCategoryId ? this.expenseCategories[index].category : undefined;
}
英文:

Ok. I figured it out from a previous project I did a couple years ago (thought I solved this before.)

So what I did was bind displayExpenseCategoryFn to the controller, so I could search through the expenseCategories array to extract the category name and display that in the input field.

&lt;mat-autocomplete #auto=&quot;matAutocomplete&quot; [displayWith]=&quot;displayExpenseCategoryFn.bind(this)&quot;&gt;
    &lt;mat-option *ngFor=&quot;let option of filteredExpenseCategories[i] | async&quot; [value]=&quot;option.id&quot;&gt;
        {{option.category}}
    &lt;/mat-option&gt;
&lt;/mat-autocomplete&gt;

I then made the following changes to the displayWith function.

displayExpenseCategoryFn(expenseCategoryId?: number): string | undefined {
    const index = this.expenseCategories.findIndex(expenseCategoryIndex =&gt; expenseCategoryIndex.id === expenseCategoryId);
    return expenseCategoryId ? this.expenseCategories[index].category : undefined;
}

huangapple
  • 本文由 发表于 2023年2月18日 23:40:56
  • 转载请务必保留本文链接:https://go.coder-hub.com/75494434.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定