Using a validation on a reactive form control that

2020-05-09 22:19发布

问题:

How can I run custom validation on this component in the FormBuilder?

For example, when a user selects an item from the dropdown onClickItem(item) how could run a validation function on the selected item from the main form component?

FormBuilder in main form component:

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

Then I could use a validator on itemName like this: itemName: [, MyValidator.itemNotUsed],

Template:

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

Dropdown-Select Component:

@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() {}

}

回答1:

You need add as provider NG_VALIDATORS, see https://medium.com/@tarik.nzl/angular-2-custom-form-control-with-validation-json-input-2b4cf9bc2d73

So, your providers becomes like

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

If you need addicional validator in the own component (else you needn't), you can implement Validator and create a function Validate like

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


回答2:

define

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

then when you you select item call

this.itemSelected.emit(item);

you can get the selected item in main component like this

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


标签: angular