2

I have reactive form validations set up as follows:

  ngOnInit(): void {
    this.userForm = this.formBuilder.group({
      status: {checked: this.selectedUser.status == 1},
      username: [this.selectedUser.username, [Validators.required, Validators.minLength(LlqaConstants.USERNAME_MIN_LENGTH)]],
      realname: [this.selectedUser.realname, [Validators.required, Validators.minLength(LlqaConstants.REALNAME_MIN_LENGTH)]],
      password: ['', this.selectedUser.passhash.length > 0 ? [Validators.required, Validators.minLength(LlqaConstants.PASSWORD_MIN_LENGTH)] : null],
      usercomment: [this.selectedUser.comment]
    });
  }

I'd like to enable the submit button, as soon as one input value is not equal to the initial value anymore. The simplest way I could find is:

disableSaveButton(): boolean {
  return !this.userform.dirty || this.userForm.invalid;
}

My problem with the dirty property ist, as soon as I enter something, dirty is true, also if I enter the same value as the initial value. I'd to have a property which tells me if one input value is not equal to the initial value. Is this possible out of the box or do I have to check each userForm.value equals to this.selectedUser.someValue?

2 Answers 2

8

I created a custom validator to solve this issue.

The validator:

export function oneValueHasToBeChangedValidator(values: { controlName: string, initialValue: string | number | boolean }[]): ValidatorFn {
  return (form: FormControl): { [key: string]: any } => {
    let sameValues = true;

    for (let comparingValues of values) {
      if (form.value[comparingValues.controlName] != comparingValues.initialValue) {
        sameValues = false;
        break;
      }
    }

    return sameValues ? {'sameValues': {values: values}} : null;
  };
}

How I took use of it:

this.userForm = this.formBuilder.group({
  status: this.selectedUser.status == 1,
  username: [this.selectedUser.username, [Validators.required, Validators.minLength(LlqaConstants.USERNAME_MIN_LENGTH)]],
  realname: [this.selectedUser.realname, [Validators.required, Validators.minLength(LlqaConstants.REALNAME_MIN_LENGTH)]],
  password: ['', [Validators.minLength(LlqaConstants.PASSWORD_MIN_LENGTH)]],
  usercomment: this.selectedUser.comment == null ? "" : this.selectedUser.comment
});

this.userForm.setValidators(oneValueHasToBeChangedValidator([{
  controlName: "status",
  initialValue: this.selectedUser.status == 1
}, {
  controlName: "username",
  initialValue: this.selectedUser.username
}, {
  controlName: "realname",
  initialValue: this.selectedUser.realname
}, {
  controlName: "password",
  initialValue: ""
}, {
  controlName: "usercomment",
  initialValue: this.selectedUser.comment == null ? "" : this.selectedUser.comment
}]));
this.userForm.updateValueAndValidity();
Sign up to request clarification or add additional context in comments.

Comments

0

You could cache the initial value as soon as you set the form object. Then change your disableSaveButton method to check the equality of the two values.

For instance:

export class MyComponent {
    initialValue: any;

    constructor(private fb: FormBuilder) {
        this.form = fb.group({...});
        this.initialValue = this.form.value;
    }

    disableSaveButton() {
        return JSON.stringify(this.initialValue) === JSON.stringify(this.form.value);
    }
}

The disable method will check if the current form value is the same as the initial value.

3 Comments

I already have the initial value in this.selectedUser.someValue. My question was if there is a more explicit property of dirty which checks this out of the box. Sorry if this was not clear.
You can try to use pristine. pristine will be true if the user has not changed the value in the UI. Its opposite is dirty. So if you instantiate your form group with default values and that has not been modified yet in the UI, I believe it will then be pristine with those initial values. If the form changes form the UI, it should no longer be pristine.
with pristine goes the same problem as with dirty. If you, for instance, add a letter, and remove it again dirty is still true and pristine false, although the input value and the initial value are the same. I solved the problem with a custom validator.

Your Answer

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