Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat(forms): allow minLength/maxLength validator to be bound to null #42565

Conversation

@iRealNirmal
Copy link
Contributor

@iRealNirmal iRealNirmal commented Jun 13, 2021

If the validator is bound to be null then no validation occurs and
attribute is not added to DOM.

For every validator type different PR will be raised as discussed in
#42378.

Closes #42267.

PR Checklist

Please check if your PR fulfills the following requirements:

PR Type

What kind of change does this PR introduce?

  • Bugfix
  • Feature
  • Code style update (formatting, local variables)
  • Refactoring (no functional changes, no api changes)
  • Build related changes
  • CI related changes
  • Documentation content changes
  • angular.io application / infrastructure changes
  • Other... Please describe:

What is the current behavior?

Null data type is not supported

Issue Number: #42267.

What is the new behavior?

Added support for null data type

Does this PR introduce a breaking change?

  • Yes
  • No

Other information

This is one of many PR which is going to be raised for adding support of null validation. One can go through conversation here
#42378 (comment)

@google-cla google-cla bot added the cla: yes label Jun 13, 2021
@pullapprove pullapprove bot requested a review from AndrewKushnir Jun 13, 2021
@iRealNirmal iRealNirmal force-pushed the iRealNirmal:addNull-in-minLength-MaxLength-Validator branch 2 times, most recently from 2dbd3da to d1cec55 Jun 13, 2021
@iRealNirmal
Copy link
Contributor Author

@iRealNirmal iRealNirmal commented Jun 14, 2021

@AndrewKushnir @petebacondarwin once this PR you gives go ahead signal I will raise it similarly for other methods as well

Copy link
Member

@petebacondarwin petebacondarwin left a comment

I might have misunderstood the plan, but I thought the idea was to implement a new enabled() method that would be used to decide whether validators in general were enabled or not; and in these minlength and maxlength validators would implement the enabled() check?

@iRealNirmal
Copy link
Contributor Author

@iRealNirmal iRealNirmal commented Jun 14, 2021

I might have misunderstood the plan, but I thought the idea was to implement a new enabled() method that would be used to decide whether validators in general were enabled or not; and in these minlength and maxlength validators would implement the enabled() check?

No you are correct, let me include it.

Copy link
Contributor

@AndrewKushnir AndrewKushnir left a comment

Thanks for the PR @iRealNirmal.

I've left some comments, but as @petebacondarwin mentioned, we'd need to implement the enabled method and use it in validators code instead of relying on the truthiness of the minlength and maxlength inputs.

Thank you.

packages/forms/src/directives/validators.ts Outdated Show resolved Hide resolved
packages/forms/src/directives/validators.ts Outdated Show resolved Hide resolved
packages/forms/src/validators.ts Outdated Show resolved Hide resolved
packages/forms/test/reactive_integration_spec.ts Outdated Show resolved Hide resolved
packages/forms/test/reactive_integration_spec.ts Outdated Show resolved Hide resolved
packages/forms/test/validators_spec.ts Outdated Show resolved Hide resolved
@iRealNirmal
Copy link
Contributor Author

@iRealNirmal iRealNirmal commented Jun 15, 2021

hey @AndrewKushnir @petebacondarwin when I converted it to enabled function and typescript began to give me error object possibly null error check screenshot below,

Screenshot_2021-06-14_at_10 51 00_PM

On the hand if I use variable directly I am not getting any error.

Screenshot_2021-06-14_at_10 52 16_PM

Seems typescript is not able to infer the type narrowing, I can even do workaround but it will be overkill.

Quick workaround can be like below

Screenshot_2021-06-15_at_10 16 02_AM

If you have any other suggestion then please let me know.

@petebacondarwin
Copy link
Member

@petebacondarwin petebacondarwin commented Jun 15, 2021

I wonder if we could structure this with an abstract base class?

@Directive()
abstract class ValidatorBase implements OnChanges, Validator {
  private _validator: ValidatorFn = nullValidator;
  private _onChange?: () => void;

  constructor(private _validatorKey: string) {}

  ngOnChanges(changes: SimpleChanges): void {
    if (this._validatorKey in changes) {
      this._validator = this._enabled() ? this._createValidator() : nullValidator;
      if (this._onChange) this._onChange();
    }
  }

  validate(control: AbstractControl): ValidationErrors|null {
    return this._validator(control);
  }

  registerOnValidatorChange(fn: () => void): void {
    this._onChange = fn;
  }

  protected abstract _createValidator(): ValidatorFn;
  protected abstract _enabled(): boolean;
}

Then you could have:

@Directive({
  selector: '[minlength][formControlName],[minlength][formControl],[minlength][ngModel]', 
  providers: [MIN_LENGTH_VALIDATOR],
  host: {'[attr.minlength]': '_enabled() ? minlength : null'}
})
export class MinLengthValidator implements Validator, OnChanges extends ValidatorBase {
  constructor() {
    super('minlength');
  }

  @Input()  minlength!: string|number|null;

  protected _createValidator(): ValidatorFn {
    // This will only be called if `this.minlength` is non-null
    return minLengthValidator(toInteger(this.minlength!));
  }

  // this may need to be public to use it in the hostbinding.
  protected _enabled(): boolean {
    return this.minlength !== null;
  }
}

@iRealNirmal
Copy link
Contributor Author

@iRealNirmal iRealNirmal commented Jun 15, 2021

@petebacondarwin yes good input but do you think it's fine If I can revised it to.

abstract class ValidatorBase implements OnChanges, Validator {
  private _validator: ValidatorFn = nullValidator;
  private _onChange?: () => void;
  protected prop: number|string|null = null;

  constructor(private _validatorKey: string) {}

  ngOnChanges(changes: SimpleChanges): void {
    if (this._validatorKey in changes) {
      this._validator = this._enabled() ? this._createValidator() : nullValidator;
      if (this._onChange) this._onChange();
    }
  }

  validate(control: AbstractControl): ValidationErrors|null {
    return this._validator(control);
  }

  registerOnValidatorChange(fn: () => void): void {
    this._onChange = fn;
  }

  protected abstract _createValidator(): ValidatorFn;
  
  // this may need to be public to use it in the hostbinding.
  protected _enabled(): boolean {
    return this.prop !== null;
  }
}


@Directive({
  selector: '[minlength][formControlName],[minlength][formControl],[minlength][ngModel]',
  providers: [MIN_LENGTH_VALIDATOR],
  host: {'[attr.minlength]': '_enabled(minlength) ? minlength : null'}
})
export class MinLengthValidator extends ValidatorBase implements Validator, OnChanges {
  constructor() {
    super('minlength');
  }

  @Input()  minlength!: string|number|null;

  prop = this.minlength;

  protected _createValidator(): ValidatorFn {
    // This will only be called if `this.minlength` is non-null
    return minLengthValidator(toInteger(this.minlength!));
  }

@petebacondarwin
Copy link
Member

@petebacondarwin petebacondarwin commented Jun 15, 2021

I don't really think that the this.prop is very beneficial, especially since it would restrict how we can compute enabled(). Remember that some validators are enabled even if their property is 0.

@iRealNirmal iRealNirmal force-pushed the iRealNirmal:addNull-in-minLength-MaxLength-Validator branch 3 times, most recently from 126289d to 5c487ed Jun 15, 2021
@iRealNirmal iRealNirmal force-pushed the iRealNirmal:addNull-in-minLength-MaxLength-Validator branch 6 times, most recently from 1e45f7d to 57cacf3 Jun 16, 2021
@iRealNirmal iRealNirmal changed the title fix(forms): allow minLength/maxLength validator to be bound to null feat(forms): allow minLength/maxLength validator to be bound to null Jul 18, 2021
Copy link
Member

@petebacondarwin petebacondarwin left a comment

Reviewed-for: public-api

Note for other public-api reviewers - the new enabled() method ought to be @internal, but it needs to be public for our tests to pass. It is marked with @nodoc to ensure it doesn't actually appear in the angular.io API docs and should be considered non-public.

packages/forms/src/directives/validators.ts Outdated Show resolved Hide resolved
@pullapprove pullapprove bot requested a review from jessicajaniuk Jul 19, 2021
@AndrewKushnir AndrewKushnir force-pushed the iRealNirmal:addNull-in-minLength-MaxLength-Validator branch from 6beabd0 to b6d2fe2 Jul 19, 2021
Copy link
Contributor

@AndrewKushnir AndrewKushnir left a comment

Reviewed-for: public-api

Copy link
Contributor

@jessicajaniuk jessicajaniuk left a comment

LGTM 🍪

Reviewed-for: public-api

@jessicajaniuk jessicajaniuk removed request for atscott and zarend Jul 19, 2021
@iRealNirmal iRealNirmal force-pushed the iRealNirmal:addNull-in-minLength-MaxLength-Validator branch from b6d2fe2 to f844fe7 Jul 20, 2021
If the validator is bound to be `null` then no validation occurs and
attribute is not added to DOM.

For every validator type different PR will be raised as discussed in
#42378.

Closes #42267.
@iRealNirmal iRealNirmal force-pushed the iRealNirmal:addNull-in-minLength-MaxLength-Validator branch from f844fe7 to 4a5f26b Jul 20, 2021
@AndrewKushnir
Copy link
Contributor

@AndrewKushnir AndrewKushnir commented Jul 21, 2021

Thanks for addressing the feedback @iRealNirmal 👍
I've started tests in Google's codebase one last time and if everything goes well, we should be able to add this PR to the merge queue. Will keep this thread updated.

@AndrewKushnir AndrewKushnir removed the request for review from jelbourn Jul 21, 2021
@AndrewKushnir
Copy link
Contributor

@AndrewKushnir AndrewKushnir commented Jul 21, 2021

@iRealNirmal FYI the checks in Google's codebase went well, so I'm adding this PR to the merge queue.

Thanks for contributing to Angular!

@dylhunn dylhunn closed this in a502279 Jul 21, 2021
@iRealNirmal
Copy link
Contributor Author

@iRealNirmal iRealNirmal commented Jul 22, 2021

thanks @AndrewKushnir on staying top for it, I will now will work on this kind of change for min and max validator. Let me know in case anything else.

@AndrewKushnir
Copy link
Contributor

@AndrewKushnir AndrewKushnir commented Jul 22, 2021

I will now will work on this kind of change for min and max validator.

Thanks for the help @iRealNirmal 👍 That sounds like a great next step!

iRealNirmal added a commit to iRealNirmal/angular that referenced this pull request Jul 28, 2021
If the validator is bound o be
ull then no validation occurs and attribute is not added to DOM.

PR already raised for minLength and maxLength valdiator (angular#42565).
Changes were dicussed in angular#42378
iRealNirmal added a commit to iRealNirmal/angular that referenced this pull request Aug 1, 2021
If the validator is bound o be
ull then no validation occurs and attribute is not added to DOM.

PR already raised for minLength and maxLength valdiator (angular#42565).
Changes were dicussed in angular#42378
iRealNirmal added a commit to iRealNirmal/angular that referenced this pull request Aug 1, 2021
If the validator is bound o be
ull then no validation occurs and attribute is not added to DOM.

PR already raised for minLength and maxLength valdiator (angular#42565).
Changes were dicussed in angular#42378
iRealNirmal added a commit to iRealNirmal/angular that referenced this pull request Aug 1, 2021
If the validator is bound o be
ull then no validation occurs and attribute is not added to DOM.

PR already raised for minLength and maxLength valdiator (angular#42565).
Changes were dicussed in angular#42378
iRealNirmal added a commit to iRealNirmal/angular that referenced this pull request Aug 6, 2021
If the validator is bound o be
ull then no validation occurs and attribute is not added to DOM.

PR already raised for minLength and maxLength valdiator (angular#42565).
Changes were dicussed in angular#42378
iRealNirmal added a commit to iRealNirmal/angular that referenced this pull request Aug 16, 2021
If the validator is bound o be
ull then no validation occurs and attribute is not added to DOM.

PR already raised for minLength and maxLength valdiator (angular#42565).
Changes were dicussed in angular#42378
iRealNirmal added a commit to iRealNirmal/angular that referenced this pull request Aug 16, 2021
If the validator is bound o be
ull then no validation occurs and attribute is not added to DOM.

PR already raised for minLength and maxLength valdiator (angular#42565).
Changes were dicussed in angular#42378
@angular-automatic-lock-bot
Copy link

@angular-automatic-lock-bot angular-automatic-lock-bot bot commented Aug 22, 2021

This issue has been automatically locked due to inactivity.
Please file a new issue if you are encountering a similar or related problem.

Read more about our automatic conversation locking policy.

This action has been performed automatically by a bot.

@angular-automatic-lock-bot angular-automatic-lock-bot bot locked and limited conversation to collaborators Aug 22, 2021
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Projects
None yet
Linked issues

Successfully merging this pull request may close these issues.

4 participants