Skip to content

Commit 809f157

Browse files
authored
feat(cdk-experimental/combobox): added additional open actions and a combobox-popup directive (#20306)
Combobox open actions * build: Added required files to listbox directory. * build: added listbox option directive and renamed listbox directive files. * build: Added required files to listbox directory. * build: added listbox option directive and renamed listbox directive files. * build: Added required files to listbox directory. * build: added listbox option directive and renamed listbox directive files. * build: Added required files to listbox directory. * build: added listbox option directive and renamed listbox directive files. * feat(dev-app/listbox): added cdk listbox example to the dev-app. * fix(listbox): removed duplicate dep in dev-app build file. * fix(listbox): deleted unused files. * refactor(combobox): changed names and made coerceOpenActionProperty simpler for this PR. * fix(combobox): updated syntax for casting. * refactor(combobox): changed casting syntax back. * fix(combobox): fixed trailing whitespace. * refactor(combobox): improved coerceOpenActions function to handle whitespace separated strings as input. * fix(combobox): split the coerceOpenActions on comma or space. * feat(combobox): added aria-expanded and aria-owns traits. * refactor(combobox): minor refactor. * feat(combobox): added logic to close popup on click outside of combobox. * test(combobox): added many tests for combobox open action features. * test(combobox): added back two failing tests, focus and sending input value to combobox. * refactor(combobox): further tests on focus. * refactor(combobox): added tabindex to allow focusing on content, and fixed the setTextContent function. * fix(combobox): removed separate coerceArray import. * fix(combobox): lint errors. * refactor(combobox): only throw error in coercing open action in dev mode, condense click and focus handlers into one. * nit(combobox): removed whitespace. * fix(combobox): removed unused imports. * feat(combobox): added combobox popup directive to handle registering panel content with panel. * nit(combobox): changed double quotes to single quotes. * nit(combobox): changed class names and parameter types. * fix(combobox): changed import to relative import.
1 parent 004afa1 commit 809f157

File tree

7 files changed

+484
-23
lines changed

7 files changed

+484
-23
lines changed

src/cdk-experimental/combobox/BUILD.bazel

+1
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,7 @@ ng_test_library(
2525
),
2626
deps = [
2727
":combobox",
28+
"//src/cdk/keycodes",
2829
"//src/cdk/testing/private",
2930
"@npm//@angular/platform-browser",
3031
],

src/cdk-experimental/combobox/combobox-module.ts

+2-1
Original file line numberDiff line numberDiff line change
@@ -10,8 +10,9 @@ import {NgModule} from '@angular/core';
1010
import {OverlayModule} from '@angular/cdk/overlay';
1111
import {CdkCombobox} from './combobox';
1212
import {CdkComboboxPanel} from './combobox-panel';
13+
import {CdkComboboxPopup} from './combobox-popup';
1314

14-
const EXPORTED_DECLARATIONS = [CdkCombobox, CdkComboboxPanel];
15+
const EXPORTED_DECLARATIONS = [CdkCombobox, CdkComboboxPanel, CdkComboboxPopup];
1516
@NgModule({
1617
imports: [OverlayModule],
1718
exports: EXPORTED_DECLARATIONS,

src/cdk-experimental/combobox/combobox-panel.ts

+13-2
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,9 @@ import {Directive, TemplateRef} from '@angular/core';
1212
import {Subject} from 'rxjs';
1313

1414
@Directive({
15+
host: {
16+
'class': 'cdk-combobox-panel'
17+
},
1518
selector: 'ng-template[cdkComboboxPanel]',
1619
exportAs: 'cdkComboboxPanel',
1720
})
@@ -24,13 +27,21 @@ export class CdkComboboxPanel<T = unknown> {
2427
contentId: string = '';
2528
contentType: AriaHasPopupValue;
2629

27-
constructor(readonly _templateRef: TemplateRef<unknown>) {}
30+
constructor(
31+
readonly _templateRef: TemplateRef<unknown>
32+
) {}
2833

29-
/** Tells the parent combobox to closet he panel and sends back the content value. */
34+
/** Tells the parent combobox to close the panel and sends back the content value. */
3035
closePanel(data?: T) {
3136
this.valueUpdated.next(data);
3237
}
3338

39+
// TODO: instead of using a focus function, potentially use cdk/a11y focus trapping
40+
focusContent() {
41+
// TODO: Use an injected document here
42+
document.getElementById(this.contentId)?.focus();
43+
}
44+
3445
/** Registers the content's id and the content type with the panel. */
3546
_registerContent(contentId: string, contentType: AriaHasPopupValue) {
3647
this.contentId = contentId;
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,55 @@
1+
/**
2+
* @license
3+
* Copyright Google LLC All Rights Reserved.
4+
*
5+
* Use of this source code is governed by an MIT-style license that can be
6+
* found in the LICENSE file at https://angular.io/license
7+
*/
8+
9+
import {Directive, Inject, InjectionToken, Input, OnInit, Optional} from '@angular/core';
10+
import {AriaHasPopupValue, CdkComboboxPanel} from './combobox-panel';
11+
12+
export const PANEL = new InjectionToken<CdkComboboxPanel>('CdkComboboxPanel');
13+
14+
let nextId = 0;
15+
16+
@Directive({
17+
selector: '[cdkComboboxPopup]',
18+
exportAs: 'cdkComboboxPopup',
19+
host: {
20+
'class': 'cdk-combobox-popup',
21+
'[attr.role]': 'role',
22+
'[id]': 'id',
23+
'tabindex': '-1'
24+
}
25+
})
26+
export class CdkComboboxPopup<T = unknown> implements OnInit {
27+
@Input()
28+
get role(): AriaHasPopupValue {
29+
return this._role;
30+
}
31+
set role(value: AriaHasPopupValue) {
32+
this._role = value;
33+
}
34+
private _role: AriaHasPopupValue = 'dialog';
35+
36+
@Input() id = `cdk-combobox-popup-${nextId++}`;
37+
38+
@Input('parentPanel') private readonly _explicitPanel: CdkComboboxPanel;
39+
40+
constructor(
41+
@Optional() @Inject(PANEL) readonly _parentPanel?: CdkComboboxPanel<T>,
42+
) { }
43+
44+
ngOnInit() {
45+
this.registerWithPanel();
46+
}
47+
48+
registerWithPanel(): void {
49+
if (this._parentPanel === null || this._parentPanel === undefined) {
50+
this._explicitPanel._registerContent(this.id, this._role);
51+
} else {
52+
this._parentPanel._registerContent(this.id, this._role);
53+
}
54+
}
55+
}

0 commit comments

Comments
 (0)