Angular 角度自定义下拉组件-选项更改时ngModel未正确更新

Angular 角度自定义下拉组件-选项更改时ngModel未正确更新,angular,Angular,我试图创建一个实现ControlValueAccessor的自定义下拉组件,但我希望能够从父组件而不是自定义下拉列表中定义选项 理想情况下,我希望在我的选择中使用ngModel,在我的选项中使用ngValue来实现它,但由于某种原因,当我在选项中使用ngValue时,我的ngModel没有接收到与当前所选选项的ngValue关联的对象 下面是我试图实现的用法的简化示例: 注意:我知道在这种情况下,我可以只使用id字段并按自己的方式进行操作,但我有一些情况希望使用ngModel和ngValue

我试图创建一个实现ControlValueAccessor的自定义下拉组件,但我希望能够从父组件而不是自定义下拉列表中定义选项

理想情况下,我希望在我的选择中使用ngModel,在我的选项中使用ngValue来实现它,但由于某种原因,当我在选项中使用ngValue时,我的ngModel没有接收到与当前所选选项的ngValue关联的对象

下面是我试图实现的用法的简化示例:

注意:我知道在这种情况下,我可以只使用id字段并按自己的方式进行操作,但我有一些情况希望使用ngModel和ngValue


ID{{user.ID}-{{user.name}
在进行任何更改之前打印用户输出是一个用户对象,这是预期的。但是,只要我更改选项,selectedUser对象的值就是所选选项(即ID#…-…)的选项标记之间的字符串,而不是对象

如果我使用
[value]=“user.id”
而不是
[ngValue]=“user”
,那么一切都会按预期工作:


ID{{user.ID}-{{user.name}
如果我使用常规选择而不是
自定义下拉列表
,则一切正常:


ID{{user.ID}-{{user.name}

以下是dropdown.ts和dropdown.html的实现:

dropdown.html


下拉列表。ts

@组件({
选择器:“下拉列表”,
供应商:[
{
提供:NG_值访问器,
useExisting:forwardRef(()=>DropdownComponent),
多:真的
}
],
templateUrl:'./dropdown.component.html',
样式URL:['./dropdown.component.scss']
})
导出类DropdownComponent实现ControlValueAccessor{
私人内在价值:任何;
获取值():任意{
返回此.innerValue;
}
设置值(值:任意){
if(this.innerValue!==值){
this.innerValue=值;
这个。onChange(值);
}
}
writeValue(值:任意){
this.innerValue=值;
}
onChange=()=>{};
onTouched=()=>{};
registerChange(fn:(:any)=>void):void{this.onChange=fn;}
registerOnTouched(fn:()=>void):void{this.onTouched=fn;}
}

如果您希望看到完整的实现,我有一个简单的stackblitz设置:


我不确定我到底错了什么,非常感谢您的帮助。

恐怕您不能在ng内容中使用html标记
,但您可以创建一个指令

@Directive(
{
  selector:'[option]'
})
export class OptionDirective implements AfterViewInit{
  @Input() ngValue:any;
  innerHTML:string="";
  constructor(private el:ElementRef)
  {
  }
  ngAfterViewInit()
  {
     this.innerHTML=this.el.nativeElement.innerHTML

  }
}
因此,您的.html变得像,请参见使用


ID{{user.ID}-{{user.name}
您的组件在一个div中包含ng内容,并且显示none

<select [ngClass]="[sizeClass]" [(ngModel)]="value">
  <option *ngFor="let option of options" [ngValue]="option.ngValue">
        {{option.innerHTML}}
   </option>
</select>
<div [style.display]="'none'">
    <ng-content></ng-content>
</div>

{{option.innerHTML}}
您可以使用ContentChildren获得选项和指令

 @ContentChildren(OptionDirective) options:QueryList<OptionDirective>
@ContentChildren(OptionDirective)选项:QueryList
你可以从中看到

注意:我在同一个文件dropdown.component中加入了指令OptionDirective(您需要在模块中声明)

更新使用指令,我们可以将其用作指令“选项”的选择器

@指令(
{
选择器:'option'//
<select [ngClass]="[sizeClass]" [(ngModel)]="value">
  <option *ngFor="let option of options" [ngValue]="option.ngValue">
        {{option.innerHTML}}
   </option>
</select>
<div [style.display]="'none'">
    <ng-content></ng-content>
</div>
 @ContentChildren(OptionDirective) options:QueryList<OptionDirective>
@Directive(
{
  selector:'option' //<--use 'option'
})
export class OptionDirective implements AfterViewInit{
  ...
}
<dropdown [(ngModel)]="selectedUser" (ngModelChange)="onUserChange($event)">
  <option *ngFor="let user of users;" [ngValue]="user">
    ID#{{user.id}} - {{user.name}}
  </option>
</dropdown>