首页 > 解决方案 > Angular 中 HTML DataList 的奇怪行为

问题描述

我已经实现了以下简单的组件来显示能够添加新条目的数据列表。

<h6 *ngIf="withHeader"><label for="select">
  {{title}}
</label></h6>
<label *ngIf="!withHeader" [ngClass]="{'required': required}" for="select">
  {{title}}
</label>
<input id="select" list="dataList" (change)="dataChanged()" [(ngModel)]="selectedValue"/>
<datalist id="dataList">
  <option value=null *ngIf="withButton">{{buttonTitle}}</option>
  <option  *ngFor="let item of data" [ngValue]="item">{{item[shownProperty] || item}}</option>
</datalist>

如果我在另一个组件中使用该组件的一个实例,它工作得非常好。如果我有一个包含两个 dataList-Components 的表单,则两个组件都将填充相同的数据。

例如 - 如果我有一个带有汽车的列表 A 和一个带有飞机的列表 B 两个列表都将填充汽车 - 至少如果用户打开下拉列表。

如果我跟踪 DOM 列表中的数据列表,A 中填充了汽车,B 中填充了飞机——应该是这样。

输入中的列表标识符是否与指向首先填充的列表的列表标识符混淆?但如果是这样,我该如何解决?输入的列表属性不允许这样调用,[list]以便我可以使用唯一标识符。

更新:

以下不起作用,因为如果我使用[list]会发生以下错误。

Property list is not provided by any applicable directives nor by input element

HTML:

<input id="select" [list]="dataListId" (change)="dataChanged()" [(ngModel)]="selectedValue"/>
<datalist [id]="dataListId">
  <option  *ngFor="let item of data" [ngValue]="item">{{item[shownProperty] || item}}</option>
</datalist>

组件.ts

import {Component, EventEmitter, Input, OnInit, Output} from '@angular/core';

@Component({
  selector: 'data-list',
  templateUrl: './data-list.component.html',
  styleUrls: ['./data-list.component.scss']
})
export class DataListComponent {
  @Input() data: any[];
  @Output() selectionChanged = new EventEmitter();
  @Input() selectedValue: any;
  @Input() dataListId: string;

  dataChanged() {
    // Change-Logic
  }

}

标签: javascripthtmlangulardomhtml-datalist

解决方案


您不能在 HTML 中多次出现相同的 id。在这种情况下,将选择第一个。尝试在创建组件实例后生成 id。您可以在您的组件上注册一个提供程序工厂,该工厂将为每个创建的实例调用。然后只需在您的组件中注入 id 即可。

const UNIQ_ID_TOKEN = new InjectionToken('ID');
let id = 0;
@Component({
  providers: [
    {
      provide: UNIQ_ID_TOKEN,
      useFactory: () => id++;
    }
  ]
})
class SelectComponent { 
  constructor(
    @Inject(UNIQ_ID_TOKEN)
    public uniqId: number
  ) {}
}

并在模板中使用注入的 uniqId。你可以想出更好的 id 生成。

<h6 *ngIf="withHeader"><label [attr.for]="{{'select-'uniqId}}">
  {{title}}
</label></h6>
<label *ngIf="!withHeader" [ngClass]="{'required': required}" [attr.for]="select">
  {{title}}
</label>
<input [attr.id]="{{'select-'uniqId}}" [attr.list]="{{'dataList-'uniqId}}" (change)="dataChanged()" [(ngModel)]="selectedValue"/>
<datalist [attr.id]="{{'dataList-'uniqId}}">
  <option value=null *ngIf="withButton">{{buttonTitle}}</option>
  <option  *ngFor="let item of data" [ngValue]="item">{{item[shownProperty] || item}}</option>
</datalist>

推荐阅读