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 循环中,并且在您选择联赛时会重新渲染。 联赛被听到编码,只是为了一个例子(练习)。但稍后它们将从外部“服务器”中获取...。该组件(侧边栏)用于以下(包装器)组件)<div class='sidebar'> <app-sidebar (liClick)="leagueChoosen($event)"></app-sidebar> </div>
【参考方案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
使用对象引用来检查是否相等,并且由于重新创建对象,它们不相等并且重新创建所选元素。
一种解决方法是确实在<select>
上使用[(ngModel)]
,但它没有解决问题的根源。
为了让它更干净,你应该使用trackBy
。
在您的组件 TS 代码中
// return the unique league key
trackLeagues(leagueEntry) return leagueEntry[1]
在模板中
*ngFor="let league of leagues.entries(); trackBy: trackLeagues"
这应该确保选定的<option>
元素没有被替换。
个人提示 - 我仍然认为最好使用FormControl
并订阅它的valueChanges
。描述如何远远超出此答案的范围。
【讨论】:
以上是关于Angular 12中的下拉(选择)在浏览器中手动更改后自动选择第一项的主要内容,如果未能解决你的问题,请参考以下文章
如何根据Angular 6同一行中的其他单元格值在AG-Grid选择下拉列表中加载不同的选项?
Angular 6 无法从提供的对象中自动选择/绑定下拉列表值