首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >角ControlValueAccessor和markAsTouched

角ControlValueAccessor和markAsTouched
EN

Stack Overflow用户
提问于 2020-05-02 21:50:23
回答 2查看 5.6K关注 0票数 13

我使用的角度9与角材料,我有一个定制的控制,通过实现ControlValueAccessor接口。一切都很好。

当表单无效时,在我的所有提交按钮中,我调用formGroup.markAllAsTouched,因为所有的角材料字段都变成红色。这样,用户就可以更好地理解哪些控件无效。

我需要用我的自定义控件实现相同的行为。怎么做?

我创建了一个stackblitz项目,以便更好地了解情况这里

EN

回答 2

Stack Overflow用户

回答已采纳

发布于 2020-05-05 06:15:15

另一个机会是使用以下方法

自定义控制代码

代码语言:javascript
复制
@Component({
  selector: 'cvl-advertising-type',
  templateUrl: './advertising-type.component.html',
  styleUrls: ['./advertising-type.component.scss'],
})
export class AdvertisingTypeComponent implements OnInit, ControlValueAccessor {
  advertisingTypes: ReadonlyArray<LookupModel>;

  onChange = (value: number) => {
  };
  onTouched = () => {
  };

  constructor(private lookupService: LookupService,
              @Self() public controlDir: NgControl) {
    controlDir.valueAccessor = this;
  }

  ngOnInit(): void {
    this.advertisingTypes = this.lookupService.advertisingTypes;
  }

  registerOnChange(fn: (value: number) => void): void {
    this.controlDir.control.valueChanges.subscribe(fn);
    this.onChange = fn;
  }

  writeValue(value: number): void {
    this.controlDir.control.setValue(value);
    this.onChange(value);
  }

  registerOnTouched(fn: any): void {
    this.onTouched = fn;
  }

  setDisabledState(isDisabled: boolean): void {
    if (isDisabled) {
      this.controlDir.control.disable();
    } else {
      this.controlDir.control.enable();
    }
  }
}

和父html表单

代码语言:javascript
复制
<cvl-advertising-type [formControl]="form.controls.advertisingType"></cvl-advertising-type>

我在查看了这个视频之后找到了这个解决方案

最后但同样重要的问题是,我不知道如何用浅表测试来测试它,因为我有以下错误

代码语言:javascript
复制
Error: NodeInjector: NOT_FOUND [NgControl]
票数 -1
EN

Stack Overflow用户

发布于 2020-05-03 18:26:22

没有内置功能用于将touched状态传播到自定义控件的内部FormControl。

您的简单选项是在ngDoCheck中检查状态,并且一旦自定义控件被触摸,内部FormControl的更新状态就会发生。

代码语言:javascript
复制
ngDoCheck() {
  if (this.formControl.touched) {
    return;
  }
  if (this.controlDir.control.touched) {
    this.formControl.markAsTouched();
  }
}

叉式斯塔克布利茨

就我个人而言,我不喜欢用ControlValueAccessor进行这种实现。我宁愿使用相同的FormControl。这可以通过将viewProvidersControlValueAccessor提供程序添加到您的自定义控件中来实现:

custom-control.component.ts

代码语言:javascript
复制
@Component({
  selector: 'my-custom-control',
  template: `
    <mat-form-field id="userType">
      <mat-label>My Custom Component</mat-label>
      <mat-select [formControlName]="controlName" (blur)="onTouched()">
        <mat-option *ngFor="let current of userTypes" [value]="current.id">{{current.name}}</mat-option>
      </mat-select>
    </mat-form-field>

  `,
   viewProviders: [{
    provide: ControlContainer,
    useFactory: (container: ControlContainer) => container,
    deps: [[new SkipSelf(), ControlContainer]],
 }]
})
export class MyCustomControl {
  @Input() controlName: string;

  userTypes: LookupModel[] = [
      new LookupModel(1, 'first'),
      new LookupModel(2, 'second')
  ];
}

父html

代码语言:javascript
复制
<form [formGroup]="form">
  <my-custom-control controlName="userTypeCustomControl"></my-custom-control>

Stackblitz示例

票数 10
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/61566769

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档