Angular 中 HTML DataList 的奇怪行为
Wierd behaviour of HTML DataList in Angular
我已经实现了以下简单组件来显示数据列表并能够添加新条目。
<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>
如果我在另一个组件中使用这个组件的一个实例,它工作得很好。如果我有一个包含两个数据列表组件的表单,则两个组件都将填充相同的数据。
例如 - 如果我有一个包含汽车的列表 A 和一个包含飞机的列表 B,这两个列表都将填充汽车 - 至少在用户打开下拉列表时是这样。
如果我跟踪 DOM 中的数据列表,列表 A 中填充了汽车,列表 B 中填充了飞机 - 应该是这样。
输入中的列表标识符是否与指向首先填充的列表的列表标识符混淆?但如果是这样,我该如何解决呢?输入的 list-属性 不允许这样调用 [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>
Component.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
}
}
您不能在 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>
我已经实现了以下简单组件来显示数据列表并能够添加新条目。
<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>
如果我在另一个组件中使用这个组件的一个实例,它工作得很好。如果我有一个包含两个数据列表组件的表单,则两个组件都将填充相同的数据。
例如 - 如果我有一个包含汽车的列表 A 和一个包含飞机的列表 B,这两个列表都将填充汽车 - 至少在用户打开下拉列表时是这样。
如果我跟踪 DOM 中的数据列表,列表 A 中填充了汽车,列表 B 中填充了飞机 - 应该是这样。
输入中的列表标识符是否与指向首先填充的列表的列表标识符混淆?但如果是这样,我该如何解决呢?输入的 list-属性 不允许这样调用 [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>
Component.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
}
}
您不能在 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>