Я пытаюсь создать пользовательский раскрывающийся компонент, который реализует ControlValueAccessor, но я хочу иметь возможность определять параметры из родительского компонента вместо настраиваемого раскрывающегося списка.
В идеале я хотел бы реализовать его, используя ngModel в моем выборе и ngValue в моих опциях, но по какой-то причине, когда я использую ngValue в опциях, мой ngModel не получает объект, связанный с ngValue для текущий выбранный вариант.
Ниже приведен упрощенный пример использования, которое я пытаюсь выполнить sh:
Примечание. В этом случае я знаю, что могу просто использовать поле id и go о моем пути, но у меня есть случаи, когда я хотел бы использовать ngModel и ngValue.
User: { id: string, name: string, address string }
<!-- This does NOT work like I expected, and selectedUser receives the label in between the options tags -->
<custom-dropdown [(ngModel)]="selectedUser" (change)="onUserChange($event)">
<option *ngFor="let user of users;" [ngValue]="user">
ID#{{user.id}} - {{user.name}}
</option>
</custom-dropdown>
Печать вывода пользователя перед внесением каких-либо изменений является объектом пользователя и ожидается. Однако, как только я изменю параметры, значением объекта selectedUser является строка между тегом параметра выбранной опции (т. Е. ID # ... - ...) вместо объекта.
Если я использую [value]="user.id"
вместо [ngValue]="user"
, все будет работать как положено:
<!-- This works as expected and selectUser gets the user object that ngValue is associated with -->
<custom-dropdown [(ngModel)]="selectedUser" (change)="onUserChange($event)">
<option *ngFor="let user of users;" [value]="user.id">
ID#{{user.id}} - {{user.name}}
</option>
</custom-dropdown>
Если я использую обычный выбор вместо custom-dropdown
, все будет работать так, как ожидается:
<!-- This works as expected and selectUser gets the user object that ngValue is associated with -->
<select [(ngModel)]="selectedUser" (change)="onUserChange($event)">
<option *ngFor="let user of users;" [ngValue]="user">
ID#{{user.id}} - {{user.name}}
</option>
</select>
Вот раскрывающиеся списки и раскрывающиеся списки. html реализации:
раскрывающиеся списки. html
<select [ngClass]="[sizeClass]" [(ngModel)]="value">
<ng-content></ng-content>
</select>
dropdown.ts
@Component({
selector: 'dropdown',
providers: [
{
provide: NG_VALUE_ACCESSOR,
useExisting: forwardRef(() => DropdownComponent),
multi: true
}
],
templateUrl: './dropdown.component.html',
styleUrls: ['./dropdown.component.scss']
})
export class DropdownComponent implements ControlValueAccessor {
private innerValue: any;
get value(): any {
return this.innerValue;
}
set value(value: any) {
if (this.innerValue !== value) {
this.innerValue = value;
this.onChange(value);
}
}
writeValue(value: any) {
this.innerValue = value;
}
onChange = (_) => {};
onTouched = () => {};
registerOnChange(fn: (_: any) => void): void { this.onChange = fn; }
registerOnTouched(fn: () => void): void { this.onTouched = fn; }
}
Если вы хотите увидеть полную реализацию, у меня есть простая настройка stackblitz:
Я не уверен, что именно я не прав, и любая помощь приветствуется ..