mirror of
https://github.com/Alfresco/alfresco-content-app.git
synced 2026-09-09 18:02:54 +00:00
[ACS-10294] KN: Personal Files: On activating the button, focus does not move into newly opened section (#5014)
This commit is contained in:
+1
@@ -9,6 +9,7 @@
|
||||
</div>
|
||||
|
||||
<fieldset
|
||||
#conditionRow
|
||||
[attr.aria-labelledby]="'conditions-group-label-' + (childCondition ? 'nested' : 'main')"
|
||||
class="aca-rule-composite-condition__form__row"
|
||||
*ngFor="let control of conditionFormControls; let i = index">
|
||||
|
||||
+34
-1
@@ -22,7 +22,7 @@
|
||||
* from Hyland Software. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
import { ComponentFixture, TestBed } from '@angular/core/testing';
|
||||
import { ComponentFixture, fakeAsync, TestBed, tick } from '@angular/core/testing';
|
||||
import { RuleCompositeConditionUiComponent } from './rule-composite-condition.ui-component';
|
||||
import { NoopTranslateModule, UnitTestingUtils } from '@alfresco/adf-core';
|
||||
import { DebugElement } from '@angular/core';
|
||||
@@ -33,6 +33,7 @@ import {
|
||||
} from '../../mock/conditions.mock';
|
||||
import { RuleSimpleConditionUiComponent } from './rule-simple-condition.ui-component';
|
||||
import { AlfrescoApiService, AlfrescoApiServiceMock } from '@alfresco/adf-content-services';
|
||||
import { FocusTrapFactory } from '@angular/cdk/a11y';
|
||||
|
||||
describe('RuleCompositeConditionUiComponent', () => {
|
||||
let fixture: ComponentFixture<RuleCompositeConditionUiComponent>;
|
||||
@@ -166,4 +167,36 @@ describe('RuleCompositeConditionUiComponent', () => {
|
||||
expect(unitTestingUtils.getAllByCSS('[conditions-group-label-nested]')).toBeTruthy();
|
||||
});
|
||||
});
|
||||
|
||||
describe('Focus management', () => {
|
||||
it('should focus the newly added simple condition', fakeAsync(() => {
|
||||
fixture.detectChanges();
|
||||
const focusTrapFactory = TestBed.inject(FocusTrapFactory);
|
||||
const focusTrapSpy = jasmine.createSpyObj('FocusTrap', ['focusFirstTabbableElement', 'destroy']);
|
||||
spyOn(focusTrapFactory, 'create').and.returnValue(focusTrapSpy);
|
||||
|
||||
unitTestingUtils.clickByDataAutomationId('add-condition-button');
|
||||
fixture.detectChanges();
|
||||
tick();
|
||||
|
||||
expect(focusTrapFactory.create).toHaveBeenCalled();
|
||||
expect(focusTrapSpy.focusFirstTabbableElement).toHaveBeenCalled();
|
||||
expect(focusTrapSpy.destroy).toHaveBeenCalled();
|
||||
}));
|
||||
|
||||
it('should focus the newly added composite condition', fakeAsync(() => {
|
||||
fixture.detectChanges();
|
||||
const focusTrapFactory = TestBed.inject(FocusTrapFactory);
|
||||
const focusTrapSpy = jasmine.createSpyObj('FocusTrap', ['focusFirstTabbableElement', 'destroy']);
|
||||
spyOn(focusTrapFactory, 'create').and.returnValue(focusTrapSpy);
|
||||
|
||||
unitTestingUtils.clickByDataAutomationId('add-group-button');
|
||||
fixture.detectChanges();
|
||||
tick();
|
||||
|
||||
expect(focusTrapFactory.create).toHaveBeenCalled();
|
||||
expect(focusTrapSpy.focusFirstTabbableElement).toHaveBeenCalled();
|
||||
expect(focusTrapSpy.destroy).toHaveBeenCalled();
|
||||
}));
|
||||
});
|
||||
});
|
||||
|
||||
+57
-11
@@ -22,7 +22,22 @@
|
||||
* from Hyland Software. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
import { Component, forwardRef, HostBinding, Input, OnChanges, OnDestroy, SimpleChanges, ViewEncapsulation } from '@angular/core';
|
||||
import {
|
||||
AfterViewInit,
|
||||
Component,
|
||||
DestroyRef,
|
||||
ElementRef,
|
||||
forwardRef,
|
||||
HostBinding,
|
||||
inject,
|
||||
Input,
|
||||
OnChanges,
|
||||
QueryList,
|
||||
SimpleChanges,
|
||||
ViewChildren,
|
||||
ViewEncapsulation
|
||||
} from '@angular/core';
|
||||
import { takeUntilDestroyed } from '@angular/core/rxjs-interop';
|
||||
import { RuleCompositeCondition } from '../../model/rule-composite-condition.model';
|
||||
import { ControlValueAccessor, FormArray, FormControl, FormGroup, NG_VALUE_ACCESSOR, ReactiveFormsModule } from '@angular/forms';
|
||||
import { RuleSimpleCondition } from '../../model/rule-simple-condition.model';
|
||||
@@ -34,6 +49,7 @@ import { MatButtonModule } from '@angular/material/button';
|
||||
import { MatMenuModule } from '@angular/material/menu';
|
||||
import { MatIconModule } from '@angular/material/icon';
|
||||
import { RuleSimpleConditionUiComponent } from './rule-simple-condition.ui-component';
|
||||
import { FocusTrapFactory } from '@angular/cdk/a11y';
|
||||
|
||||
@Component({
|
||||
imports: [
|
||||
@@ -60,16 +76,21 @@ import { RuleSimpleConditionUiComponent } from './rule-simple-condition.ui-compo
|
||||
}
|
||||
]
|
||||
})
|
||||
export class RuleCompositeConditionUiComponent implements ControlValueAccessor, OnDestroy, OnChanges {
|
||||
export class RuleCompositeConditionUiComponent implements ControlValueAccessor, OnChanges, AfterViewInit {
|
||||
@HostBinding('class.aca-secondaryBackground')
|
||||
@Input()
|
||||
secondaryBackground = false;
|
||||
|
||||
@HostBinding('class.aca-childCompositeCondition')
|
||||
@Input()
|
||||
childCondition = false;
|
||||
|
||||
@Input()
|
||||
readOnly = false;
|
||||
|
||||
@ViewChildren('conditionRow', { read: ElementRef })
|
||||
private readonly conditionRows: QueryList<ElementRef<HTMLElement>>;
|
||||
|
||||
readonly isOrImplemented = false;
|
||||
|
||||
form = new FormGroup({
|
||||
@@ -79,23 +100,31 @@ export class RuleCompositeConditionUiComponent implements ControlValueAccessor,
|
||||
simpleConditions: new FormArray([])
|
||||
});
|
||||
|
||||
private formSubscription = this.form.valueChanges.subscribe((value: any) => {
|
||||
this.onChange(value);
|
||||
this.onTouch();
|
||||
});
|
||||
|
||||
public invertedControl = this.form.get('inverted') as FormControl;
|
||||
public booleanModeControl = this.form.get('booleanMode') as FormControl;
|
||||
|
||||
private readonly destroyRef = inject(DestroyRef);
|
||||
private readonly focusTrapFactory = inject(FocusTrapFactory);
|
||||
|
||||
constructor() {
|
||||
this.form.valueChanges.pipe(takeUntilDestroyed()).subscribe((value: RuleCompositeCondition) => {
|
||||
this.onChange(value);
|
||||
this.onTouch();
|
||||
});
|
||||
}
|
||||
|
||||
get compositeConditionsFormArray(): FormArray {
|
||||
return this.form.get('compositeConditions') as FormArray;
|
||||
}
|
||||
|
||||
get simpleConditionsFormArray(): FormArray {
|
||||
return this.form.get('simpleConditions') as FormArray;
|
||||
}
|
||||
|
||||
get conditionFormControls(): FormControl[] {
|
||||
return [...(this.compositeConditionsFormArray.controls as FormControl[]), ...(this.simpleConditionsFormArray.controls as FormControl[])];
|
||||
}
|
||||
|
||||
get hasNoConditions(): boolean {
|
||||
return this.conditionFormControls.length === 0;
|
||||
}
|
||||
@@ -103,6 +132,12 @@ export class RuleCompositeConditionUiComponent implements ControlValueAccessor,
|
||||
onChange: (condition: RuleCompositeCondition) => void = () => undefined;
|
||||
onTouch: () => void = () => undefined;
|
||||
|
||||
ngAfterViewInit(): void {
|
||||
this.conditionRows.changes.pipe(takeUntilDestroyed(this.destroyRef)).subscribe(() => {
|
||||
this.focusLastCondition();
|
||||
});
|
||||
}
|
||||
|
||||
writeValue(value: RuleCompositeCondition) {
|
||||
this.form.get('inverted').setValue(value.inverted);
|
||||
this.form.get('booleanMode').setValue(value.booleanMode);
|
||||
@@ -148,10 +183,6 @@ export class RuleCompositeConditionUiComponent implements ControlValueAccessor,
|
||||
this.compositeConditionsFormArray.push(new FormControl(newCondition));
|
||||
}
|
||||
|
||||
ngOnDestroy() {
|
||||
this.formSubscription.unsubscribe();
|
||||
}
|
||||
|
||||
ngOnChanges(changes: SimpleChanges) {
|
||||
const readOnly = changes['readOnly']?.currentValue;
|
||||
|
||||
@@ -165,4 +196,19 @@ export class RuleCompositeConditionUiComponent implements ControlValueAccessor,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private focusLastCondition(): void {
|
||||
const rows = this.conditionRows.toArray();
|
||||
const lastRow = rows[rows.length - 1]?.nativeElement;
|
||||
|
||||
if (!lastRow) {
|
||||
return;
|
||||
}
|
||||
|
||||
setTimeout(() => {
|
||||
const focusTrap = this.focusTrapFactory.create(lastRow);
|
||||
focusTrap.focusFirstTabbableElement();
|
||||
focusTrap.destroy();
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user