2

I have a simple custom form control with one input:

const NGX_HELLO_VALUE_ACCESSOR = {
    provide: NG_VALUE_ACCESSOR,
    useExisting: forwardRef(() => HelloComponent),
    multi: true
};

const NGX_HELLO_VALIDATORS = {
    provide: NG_VALIDATORS,
    useExisting: forwardRef(() => HelloComponent),
    multi: true
};

@Component({
    selector: 'hello',
    template: `<p>Value in custom form control: {{value}}</p>`,
    providers: [NGX_HELLO_VALUE_ACCESSOR, NGX_HELLO_VALIDATORS]
})
export class HelloComponent implements OnChanges, ControlValueAccessor, Validator  {

    @Input() maxLength: number;

    value: string;
    onChangeCb: (_: any) => void = () => { };
    onTouchedCb: () => void = () => { };

    ngOnChanges(changes: SimpleChanges): void {
        //trigger validation
    }

    writeValue(value: any): void {
        this.value = value;
    }

    registerOnChange(fn: any): void {
        this.onChangeCb = fn;
    }

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

    validate(control: FormControl): ValidationErrors {
        if(this.value && this.value.length > this.maxLength) {
            return {
                tooLong: this.maxLength
            };
        }
        return null;
    }
}

which works fine. Whenever value changes, angular calls validate and the control is validated. The question is how to run validation when the @Input maxLength is changed?

I have created stackblitz example to play around.

2 Answers 2

1
 ngOnChanges(changes: SimpleChanges): void {
    //trigger validation
    this.onChangeCb(this.value);
  }

do the trick, it seems angular rerun validation on value change.

Forked stackblitz

Sign up to request clarification or add additional context in comments.

2 Comments

Thanks, it does revalidate the control, unfortunately calling onChangeCb sets the dirty flag on the form control. Any ideas how to prevent that?
No, since it seems that you can't access the formControl through the controlValueAccessor. But maybe you can trigger the onChangeCb only if a value is already set, ( then already dirty )
0

There's a callback provided by the Validator interface for this exact case with registerOnValidatorChange.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.