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=86285b543b7d4f594599365a4e78c474d7ebb0ae;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 124214f31315..14fb82341846 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 3a2a0f0e8dfa..770bc09854a4 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 07030dba59f3..4d49c639b329 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 87d5ac29f303..03a4b95e79e8 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 d1cc8ed6280b..dff17050b012 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) => {