From: Tiago Melo Date: Thu, 23 May 2019 16:18:22 +0000 (+0000) Subject: mgr/dashboard: Subscribe to changes when RequiredIf is used X-Git-Tag: v15.1.0~2649^2 X-Git-Url: http://git-server-git.apps.pok.os.sepia.ceph.com/?a=commitdiff_plain;h=refs%2Fpull%2F28231%2Fhead;p=ceph.git mgr/dashboard: Subscribe to changes when RequiredIf is used 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 --- diff --git a/src/pybind/mgr/dashboard/frontend/src/app/ceph/nfs/nfs-form/nfs-form.component.ts b/src/pybind/mgr/dashboard/frontend/src/app/ceph/nfs/nfs-form/nfs-form.component.ts index 124214f3131..14fb8234184 100644 --- a/src/pybind/mgr/dashboard/frontend/src/app/ceph/nfs/nfs-form/nfs-form.component.ts +++ b/src/pybind/mgr/dashboard/frontend/src/app/ceph/nfs/nfs-form/nfs-form.component.ts @@ -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) { diff --git a/src/pybind/mgr/dashboard/frontend/src/app/ceph/rgw/rgw-user-form/rgw-user-form.component.ts b/src/pybind/mgr/dashboard/frontend/src/app/ceph/rgw/rgw-user-form/rgw-user-form.component.ts index 3a2a0f0e8df..770bc09854a 100644 --- a/src/pybind/mgr/dashboard/frontend/src/app/ceph/rgw/rgw-user-form/rgw-user-form.component.ts +++ b/src/pybind/mgr/dashboard/frontend/src/app/ceph/rgw/rgw-user-form/rgw-user-form.component.ts @@ -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() { @@ -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; diff --git a/src/pybind/mgr/dashboard/frontend/src/app/ceph/rgw/rgw-user-s3-key-modal/rgw-user-s3-key-modal.component.ts b/src/pybind/mgr/dashboard/frontend/src/app/ceph/rgw/rgw-user-s3-key-modal/rgw-user-s3-key-modal.component.ts index 07030dba59f..4d49c639b32 100644 --- a/src/pybind/mgr/dashboard/frontend/src/app/ceph/rgw/rgw-user-s3-key-modal/rgw-user-s3-key-modal.component.ts +++ b/src/pybind/mgr/dashboard/frontend/src/app/ceph/rgw/rgw-user-s3-key-modal/rgw-user-s3-key-modal.component.ts @@ -37,7 +37,6 @@ export class RgwUserS3KeyModalComponent { ) { this.resource = this.i18n('S3 Key'); this.createForm(); - this.listenToChanges(); } createForm() { @@ -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 diff --git a/src/pybind/mgr/dashboard/frontend/src/app/ceph/rgw/rgw-user-subuser-modal/rgw-user-subuser-modal.component.ts b/src/pybind/mgr/dashboard/frontend/src/app/ceph/rgw/rgw-user-subuser-modal/rgw-user-subuser-modal.component.ts index 87d5ac29f30..03a4b95e79e 100644 --- a/src/pybind/mgr/dashboard/frontend/src/app/ceph/rgw/rgw-user-subuser-modal/rgw-user-subuser-modal.component.ts +++ b/src/pybind/mgr/dashboard/frontend/src/app/ceph/rgw/rgw-user-subuser-modal/rgw-user-subuser-modal.component.ts @@ -38,7 +38,6 @@ export class RgwUserSubuserModalComponent { ) { this.resource = this.i18n('Subuser'); this.createForm(); - this.listenToChanges(); } createForm() { @@ -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. */ diff --git a/src/pybind/mgr/dashboard/frontend/src/app/shared/forms/cd-validators.ts b/src/pybind/mgr/dashboard/frontend/src/app/shared/forms/cd-validators.ts index d1cc8ed6280..dff17050b01 100644 --- a/src/pybind/mgr/dashboard/frontend/src/app/shared/forms/cd-validators.ts +++ b/src/pybind/mgr/dashboard/frontend/src/app/shared/forms/cd-validators.ts @@ -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) => {