Skip to content

Commit

Permalink
mgr/dashboard: Subscribe to changes when RequiredIf is used
Browse files Browse the repository at this point in the history
FormControls that use 'requiredIf' validators depend on the state of other
controls.
To prevent that some of the state changes are not tracked, we now automatically
subscribe to the prerequsited controls and update the validation of the parent
control.

Fixes: https://tracker.ceph.com/issues/40017

Signed-off-by: Tiago Melo <tmelo@suse.com>
(cherry picked from commit 86285b5)
  • Loading branch information
Tiago Melo committed May 30, 2019
1 parent 50f8b3a commit d4a937e
Show file tree
Hide file tree
Showing 5 changed files with 12 additions and 62 deletions.
Expand Up @@ -201,10 +201,6 @@ export class NfsFormComponent implements OnInit {
CdValidators.requiredIf({ security_label: true, 'fsal.name': 'CEPH' })
)
});

this.nfsForm.get('protocolNfsv4').valueChanges.subscribe(() => {
this.nfsForm.get('pseudo').updateValueAndValidity({ emitEvent: false });
});
}

resolveModel(res) {
Expand Down
Expand Up @@ -62,7 +62,6 @@ export class RgwUserFormComponent implements OnInit {
this.s3keyLabel = this.i18n('S3 Key');
this.capabilityLabel = this.i18n('capability');
this.createForm();
this.listenToChanges();
}

createForm() {
Expand Down Expand Up @@ -136,39 +135,6 @@ export class RgwUserFormComponent implements OnInit {
});
}

listenToChanges() {
// Reset the validation status of various controls, especially those that are using
// the 'requiredIf' validator. This is necessary because the controls itself are not
// validated again if the status of their prerequisites have been changed.
this.userForm.get('generate_key').valueChanges.subscribe(() => {
['access_key', 'secret_key'].forEach((path) => {
this.userForm.get(path).updateValueAndValidity({ onlySelf: true });
});
});
this.userForm.get('user_quota_enabled').valueChanges.subscribe(() => {
['user_quota_max_size', 'user_quota_max_objects'].forEach((path) => {
this.userForm.get(path).updateValueAndValidity({ onlySelf: true });
});
});
this.userForm.get('user_quota_max_size_unlimited').valueChanges.subscribe(() => {
this.userForm.get('user_quota_max_size').updateValueAndValidity({ onlySelf: true });
});
this.userForm.get('user_quota_max_objects_unlimited').valueChanges.subscribe(() => {
this.userForm.get('user_quota_max_objects').updateValueAndValidity({ onlySelf: true });
});
this.userForm.get('bucket_quota_enabled').valueChanges.subscribe(() => {
['bucket_quota_max_size', 'bucket_quota_max_objects'].forEach((path) => {
this.userForm.get(path).updateValueAndValidity({ onlySelf: true });
});
});
this.userForm.get('bucket_quota_max_size_unlimited').valueChanges.subscribe(() => {
this.userForm.get('bucket_quota_max_size').updateValueAndValidity({ onlySelf: true });
});
this.userForm.get('bucket_quota_max_objects_unlimited').valueChanges.subscribe(() => {
this.userForm.get('bucket_quota_max_objects').updateValueAndValidity({ onlySelf: true });
});
}

ngOnInit() {
this.editing = this.router.url.startsWith(`/rgw/user/${URLVerbs.EDIT}`);
this.action = this.editing ? this.actionLabels.EDIT : this.actionLabels.CREATE;
Expand Down
Expand Up @@ -37,7 +37,6 @@ export class RgwUserS3KeyModalComponent {
) {
this.resource = this.i18n('S3 Key');
this.createForm();
this.listenToChanges();
}

createForm() {
Expand All @@ -49,17 +48,6 @@ export class RgwUserS3KeyModalComponent {
});
}

listenToChanges() {
// Reset the validation status of various controls, especially those that are using
// the 'requiredIf' validator. This is necessary because the controls itself are not
// validated again if the status of their prerequisites have been changed.
this.formGroup.get('generate_key').valueChanges.subscribe(() => {
['access_key', 'secret_key'].forEach((path) => {
this.formGroup.get(path).updateValueAndValidity({ onlySelf: true });
});
});
}

/**
* Set the 'viewing' flag. If set to TRUE, the modal dialog is in 'View' mode,
* otherwise in 'Add' mode. According to the mode the dialog and its controls
Expand Down
Expand Up @@ -38,7 +38,6 @@ export class RgwUserSubuserModalComponent {
) {
this.resource = this.i18n('Subuser');
this.createForm();
this.listenToChanges();
}

createForm() {
Expand All @@ -52,17 +51,6 @@ export class RgwUserSubuserModalComponent {
});
}

listenToChanges() {
// Reset the validation status of various controls, especially those that are using
// the 'requiredIf' validator. This is necessary because the controls itself are not
// validated again if the status of their prerequisites have been changed.
this.formGroup.get('generate_secret').valueChanges.subscribe(() => {
['secret_key'].forEach((path) => {
this.formGroup.get(path).updateValueAndValidity({ onlySelf: true });
});
});
}

/**
* Validates whether the subuser already exists.
*/
Expand Down
Expand Up @@ -100,7 +100,19 @@ export class CdValidators {
* @return {ValidatorFn} Returns the validator function.
*/
static requiredIf(prerequisites: Object, condition?: Function | undefined): ValidatorFn {
let isWatched = false;

return (control: AbstractControl): ValidationErrors | null => {
if (!isWatched && control.parent) {
Object.keys(prerequisites).forEach((key) => {
control.parent.get(key).valueChanges.subscribe(() => {
control.updateValueAndValidity({ emitEvent: false });
});
});

isWatched = true;
}

// Check if all prerequisites matches.
if (
!Object.keys(prerequisites).every((key) => {
Expand Down

0 comments on commit d4a937e

Please sign in to comment.