Angular 12中的下拉(选择)在浏览器中手动更改后自动选择第一项

Posted

技术标签:

【中文标题】Angular 12中的下拉(选择)在浏览器中手动更改后自动选择第一项【英文标题】:Dropdown(select) in Angular 12 is automatically selecting first item, after manual change in browser 【发布时间】:2021-11-11 11:14:02 【问题描述】:

给定以下组件 html

<select (change)="leagueChoosen($event)">
    <option disabled></option>
    <option *ngFor="let league of leagues.entries()" value=league[1]> league[0] </option>
</select>

联赛在哪里:

leagues:Map<string,number> = new Map([["PORTUGAL 1", 35],["BELGIUM 1", 3], ["GERMANY 2", 18]])

所以,问题是,每当我在下拉列表中手动选择一个项目时,后台逻辑是正确的 [函数 LeagueChoosen() ] 正在正确地完成它的工作,但是,之后自动列表中的第一个项目(空白一)被自动选中,因此下拉文本为空白。

更新:(我也是 Angular 的新手) 有3个组件:侧边栏、内容、包装器(前2个的父级)

<!-- sidebar -->
<select (change)="leagueChoosen($event)">
  <option></option>
  <option *ngFor="let league of leagues.entries()" value=league[1]>league[0]
</option>
</select>

<!-- content -->
<table>
   <caption>Football<app-button (btnClick)="Delete()" text="Delete" float="right"></app-button></caption>
   <thead>
    <th style="text-align: left;">data[0]==undefined?"":data[0].liga_header</th>
    <th colspan="3">Конечен тип</th>
    <th colspan="3">Голови</th>
</thead>
<tbody>
    <tr *ngFor="let match of data">
        <td>match==undefined?"":match.broj - match==undefined?"":match.datum_vreme.substring(6,match.datum_vreme.length - 2) | date:"HH:mm" - match==undefined?"":match.tim1 - match==undefined?"":match.tim2</td>
        <td>match==undefined?"":match.k1</td>
        <td>match==undefined?"":match.kx</td>
        <td>match==undefined?"":match.k2</td>
        <td>match==undefined?"":match.kgg3plus</td>
        <td>match==undefined?"":match.k0do2</td>
        <td>match==undefined?"":match.k3plus</td>
    </tr>
</tbody>
 <!-- wrapper -->
 <div class='sidebar'>
 <app-sidebar (liClick)="leagueChoosen($event)"></app-sidebar>
 </div>
 <div class='content'>
 <ul>
     <li *ngFor="let league of data"><app-content 
         (dlt)="Delete(league)" 
         [data]="league">
     </app-content>
     </li>
 </ul>
 </div>

【问题讨论】:

这是一种 React 的做事方式。您可以使用反应式表单或模板驱动表单吗?为了解决这个问题,我想我需要知道在其中呈现这个选择的整个模板(可能还有所有父级到根目录)。我怀疑它嵌套在 *ngFor 循环中,并且在您选择联赛时会重新渲染。 联赛被听到编码,只是为了一个例子(练习)。但稍后它们将从外部“服务器”中获取...。该组件(侧边栏)用于以下(包装器)组件)&lt;div class='sidebar'&gt; &lt;app-sidebar (liClick)="leagueChoosen($event)"&gt;&lt;/app-sidebar&gt; &lt;/div&gt; 【参考方案1】:

似乎问题出在您的 html 中,您没有为 select 框提供默认值。

试试下面的版本:

<select [(ngModel)]="'35'" (change)="leagueChoosen($event)">
  <option></option>
  <option *ngFor="let league of leagues.entries()" [value]="league[1]">league[0]
  </option>
</select>

【讨论】:

【参考方案2】:

问题是您正在循环遍历leagues.entries(),它会在每次模板检查时重新运行,这发生在(更改)回调之后。因此,选定的 DOM 元素被替换,因为 entries 每次都会创建新对象。默认情况下ngFor使用对象引用来检查是否相等,并且由于重新创建对象,它们不相等并且重新创建所选元素。

一种解决方法是确实在&lt;select&gt; 上使用[(ngModel)],但它没有解决问题的根源。

为了让它更干净,你应该使用trackBy

在您的组件 TS 代码中

// return the unique league key
trackLeagues(leagueEntry)  return leagueEntry[1] 

在模板中

*ngFor="let league of leagues.entries(); trackBy: trackLeagues"

这应该确保选定的&lt;option&gt; 元素没有被替换。

个人提示 - 我仍然认为最好使用FormControl 并订阅它的valueChanges。描述如何远远超出此答案的范围。

【讨论】:

以上是关于Angular 12中的下拉(选择)在浏览器中手动更改后自动选择第一项的主要内容,如果未能解决你的问题,请参考以下文章

如何手动切换 angular-ui-select 下拉菜单

如何根据Angular 6同一行中的其他单元格值在AG-Grid选择下拉列表中加载不同的选项?

Angular 6 无法从提供的对象中自动选择/绑定下拉列表值

Angular2 下拉菜单恢复到以前选择的选项

使用Angular.js中的cookie填充选择的相关下拉列表

Angular - 我正在尝试从数组对象值的下拉菜单中填充和选择