Angular TypeScript中Map.get返回undefined 虽Map已含7个值
Angular表单绑定值作为Map键取值始终返回undefined问题
问题现象
在Angular + TypeScript开发过程中出现异常:将表单元素双向绑定的数值类型变量extra1作为键,调用Map实例的get()方法时,方法始终返回undefined,即使该Map中已经存储了7个有效键值对。
问题相关代码
组件TypeScript代码
extraById = new Map<number, Extra>(); @Input() extra1: number = -1; formChanged(carConfigurationFormChanged: any) { const index = this.extra1; const record: Extra | undefined = this.extraById.get(index); this.gesamtpreis = "" + record?.preis?.toString() + " " + Math.random().toString(); }
组件模板代码
<div class="card my-5"> <div class="card-body"> <form #carConfigurationForm="ngForm" (change)="formChanged(carConfigurationForm)"> <div class="form-group"> <label for="extra">Extra 1 </label> <select name="extra1" class="btn btn-secondary dropdown-toggle" [(ngModel)]="extra1"> <option value="default">Kein Extra</option> <option *ngFor="let extra of selectExtra" [value]="extra.id">{{extra.name}} {{extra.preis}}€</option> </select> </div> <div class="form-group"> <label for="gesamtpreis">Gesamt </label> <span name="gesamtpreis" [innerHTML]="gesamtpreis" ngModel="gesamtpreis"></span> </div> </form> </div> </div>
问题根因
Map的键匹配采用SameValueZero算法(和严格相等===逻辑基本一致),不会做隐式类型转换,数字类型的1和字符串类型的"1"会被判定为不同的键。
Angular模板中option标签的[value]属性仅支持字符串类型传值:哪怕绑定的是数值类型的extra.id,最终绑定到ngModel上的extra1也会被自动转换为字符串类型。可以在取值前打印typeof this.extra1验证,会发现输出为string,和Map中存储的number类型键类型不匹配,因此始终无法命中对应键值对。
除此之外默认选项硬编码的value="default"是字符串值,选中时也会把extra1赋值为字符串,和初始定义的number类型冲突。
修复方案
- 将所有option标签上的
[value]替换为[ngValue],该指令支持保留绑定值的原始类型,不会自动做字符串转换 - 将默认选项的取值从硬编码字符串
"default"替换为和初始值一致的数字-1,保证类型统一
修复后select部分的模板代码如下:
<select name="extra1" class="btn btn-secondary dropdown-toggle" [(ngModel)]="extra1"> <option [ngValue]="-1">Kein Extra</option> <option *ngFor="let extra of selectExtra" [ngValue]="extra.id">{{extra.name}} {{extra.preis}}€</option> </select>
内容的提问来源于stack exchange,提问作者Adder
相关产品推荐
相关产品推荐

