【问题标题】:Using a validation on a reactive form control that is a component在作为组件的反应式表单控件上使用验证
【发布时间】:2018-12-16 09:51:00
【问题描述】:

如何在 FormBuilder 中对此组件运行自定义验证?

例如,当用户从onClickItem(item)下拉列表中选择一个项目时 如何从主表单组件中对选定的item 运行验证函数?

主表单组件中的FormBuilder:

this.itemForm = this.fb.group({
   name: ['', [Validators.required, Validators.minLength(3)]],
   description: ['', [Validators.required, Validators.minLength(10)]],
   itemName: [] // run validation on this component
});

然后我可以像这样在 itemName 上使用验证器:itemName: [, MyValidator.itemNotUsed],

模板:

<app-dropdown-select formControlName="itemName"
     [dropdownItems]="items">
</app-dropdown-select>

下拉选择组件:

@Component({
  selector: 'app-dropdown-select',
  templateUrl: './dropdown-select.component.html',
  styleUrls: ['./dropdown-select.component.scss'],
  providers: [
    {
      provide: NG_VALUE_ACCESSOR,
      useExisting: forwardRef(() => DropdownSelectComponent),
      multi: true
    }
  ]
})
export class DropdownSelectComponent implements ControlValueAccessor {

  @Input() combinedInput: boolean;
  @Input() dropdownItems: DropdownItem[];
  _selectedItem: DropdownItem;
  showList: boolean;
  buttonIcon: string;

  propagateChange = (_: any) => {};

  set selectedItem(value) {
    this._selectedItem = value;
    this.propagateChange(this._selectedItem);
  }

  get selectedItem() {
    return this._selectedItem;
  }

  constructor(private el: ElementRef) { }

  OnInit() {
    this.buttonIcon = BUTTON_ICON_INACTIVE;
    this.selectedItem = this.dropdownItems[0];
    console.log(this.dropdownItems);
  }

  onClick() {
    this.toggleShowList();
  }

  toggleShowList() {
    this.showList = !this.showList;
    if (!this.showList) {
      this.buttonIcon = BUTTON_ICON_INACTIVE;
    } else {
      this.buttonIcon = BUTTON_ICON_ACTIVE;
    }
  }

  onClickItem(item) {
    this.showList = false;
    this.selectedItem = item;
    this.propagateChange(this.selectedItem);
  }

  writeValue(value: any) {
    if (value !== undefined) {
      this.selectedItem = value;
    }
  }

  registerOnChange(fn) {
    console.log('register change');
    this.propagateChange = fn;
  }

  registerOnTouched() {}

}

【问题讨论】:

  • 您可以将 FormControl 传递给组件,这将使您的生活更轻松。 (要传递 FormControl,您需要一个 Input() 并制作类似 [control]="formGroup.get('input')" 的内容
  • 我宁愿在组件之外定义验证器,然后将它应用到formbuilder中的控件,它认为这样更易于维护

标签: angular


【解决方案1】:

您需要添加为提供者 NG_VALIDATORS,请参阅https://medium.com/@tarik.nzl/angular-2-custom-form-control-with-validation-json-input-2b4cf9bc2d73

所以,你的供应商变成了

providers: [
{
  provide: NG_VALUE_ACCESSOR,
  useExisting: forwardRef(() => DropdownSelectComponent),
  multi: true,
},
{
  provide: NG_VALIDATORS,
  useExisting: forwardRef(() => DropdownSelectComponent),
  multi: true,
}

如果你需要在自己的组件中添加额外的验证器(否则你不需要),你可以实现 Validator 并创建一个函数 Validate 像

public validate(c: FormControl) {
    //implement your logic here
    let error:boolean
    return error?{
        customError:"ERROR"
    }:null;
}

【讨论】:

  • 这得到了一个在下拉组件中工作的验证器,现在如果想在表单组件中运行它怎么办: itemName: [, MyValidator.itemNotUsed] 让它更干净
  • @coder,如果你想让验证器不在组件中,你应该能够毫无问题地做到这一点。我用两个愚蠢的自定义组件举了一个例子。一种具有验证功能,另一种没有验证功能。见stackblitz.com/edit/…
【解决方案2】:

定义

@Output('itemSelected') itemSelected = new EventEmitter(); //in DropdownSelectComponent

然后当你选择项目调用时

this.itemSelected.emit(item);

您可以像这样在主组件中获取所选项目

<app-dropdown-select formControlName="itemName"
     [dropdownItems]="items" (itemSelected)="doValidation($event)">
</app-dropdown-select>

【讨论】:

  • Coder 正在寻找“验证器”,当您制作自定义表单控件时,您正在尝试制作类似于输入或选择的控件。您不需要使用 (itemSelected) -Angular 会为您处理好它-
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2018-07-08
  • 2020-04-06
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多