combobox
Compose a searchable listbox with one ng-combobox root and semantic child
elements identified by combobox part classes. AngularTS ng-model, filters, and
event expressions remain the source of truth for query and selected-value state.
AngularCSS supplies popup disclosure, active-descendant navigation, disabled
handling, collision placement, and visual state.
<div
ng-combobox
ng-on-angularcss:combobox-select="selected=$event.detail.value; query=selected"
>
<header>
<input
aria-label="Framework"
ng-model="query"
placeholder="Select a framework"
/>
<button type="button" aria-label="Show frameworks" value="toggle"></button>
</header>
<aside aria-label="Framework options">
<p>No items found.</p>
<div>
<ul>
<li
ng-repeat="framework in frameworks | filter:query"
data-value="{{ framework }}"
ng-attr-aria-selected="{{ selected === framework }}"
>
{{ framework }}
</li>
</ul>
</div>
</aside>
</div>
Add auto-highlight when opening or filtering should highlight the first
enabled result. Without it, the popup opens without an active option until the
user presses an arrow key. Bind angularcss:combobox-open-change when the root
uses controlled open="{{ state.open }}" state.
For multiple selection, add multiple, render chips from AngularTS state, and
bind each option’s aria-selected value. Selection events include
multiple: true; angularcss:combobox-remove-last only signals Backspace on an
empty chip input. AngularCSS never replaces the application’s collection.
Example
View source
<!doctype html>
<html lang="en">
<head>
<meta charset="utf-8" />
<meta name="viewport" content="width=device-width, initial-scale=1" />
<title>AngularCSS Combobox</title>
<link rel="stylesheet" href="../../css/preflight.css" />
<link rel="stylesheet" href="../../css/angular.css" />
<link rel="stylesheet" href="../example.css" />
<script src="../../js/angular-ts.umd.js"></script>
<script src="../../js/angular-css.umd.js"></script>
</head>
<body
ng-app="angular.css"
ng-cloak
ng-init="frameworks=['Next.js','SvelteKit','Nuxt.js','Remix','Astro']; basic={query:'',selected:''}; automatic={query:'',selected:''}"
data-example="combobox-auto-highlight combobox-basic combobox-demo"
>
<main class="visual-example">
<div
id="basic-combobox"
ng-combobox
ng-on-angularcss:combobox-select="basic.selected=$event.detail.value; basic.query=$event.detail.value"
>
<header>
<input
aria-label="Framework"
ng-model="basic.query"
placeholder="Select a framework"
/>
<button
type="button"
aria-label="Show frameworks"
value="toggle"
></button>
</header>
<aside aria-label="Framework options">
<p>No items found.</p>
<div>
<ul>
<li
ng-repeat="framework in frameworks | filter:basic.query"
ng-attr-aria-selected="{{ basic.selected === framework }}"
>
{{ framework }}
</li>
</ul>
</div>
</aside>
</div>
<div
id="auto-combobox"
ng-combobox
auto-highlight
ng-on-angularcss:combobox-select="automatic.selected=$event.detail.value; automatic.query=$event.detail.value"
>
<header>
<input
aria-label="Auto-highlight framework"
ng-model="automatic.query"
placeholder="Select a framework"
/>
<button
type="button"
aria-label="Show auto-highlight frameworks"
value="toggle"
></button>
</header>
<aside aria-label="Auto-highlight framework options">
<p>No items found.</p>
<div>
<ul>
<li
ng-repeat="framework in frameworks | filter:automatic.query"
ng-attr-aria-selected="{{ automatic.selected === framework }}"
>
{{ framework }}
</li>
</ul>
</div>
</aside>
</div>
<output class="visually-hidden" aria-live="polite">
Basic: <span ng-bind="basic.selected || 'none'"></span>. Automatic:
<span ng-bind="automatic.selected || 'none'"></span>.
</output>
</main>
</body>
</html>
Reference Workflows
Clear, disabled, grouped, input-addon, invalid, and separate popup-trigger compositions are functional in this artifact. Put the selected-value label inside the direct toggle button. When a composition needs a compact button inside an input shell, use a direct native button.
View source
<!doctype html>
<html lang="en">
<head>
<meta charset="utf-8" />
<meta name="viewport" content="width=device-width, initial-scale=1" />
<title>AngularCSS Combobox Workflows</title>
<link rel="stylesheet" href="../../css/preflight.css" />
<link rel="stylesheet" href="../../css/angular.css" />
<link rel="stylesheet" href="../example.css" />
<script src="../../js/angular-ts.umd.js"></script>
<script src="../../js/angular-css.umd.js"></script>
</head>
<body
ng-app="angular.css"
ng-cloak
ng-init="frameworks=['Next.js','SvelteKit','Nuxt.js','Remix','Astro']; clearState={query:'Next.js',selected:'Next.js'}; grouped={query:'',selected:''}; invalidState={query:'',selected:''}; inputGroupState={query:'',selected:''}; popup={query:'',selected:'Select country'}; timezoneGroups=[{value:'Americas',items:['(GMT-5) New York','(GMT-8) Los Angeles','(GMT-6) Chicago','(GMT-5) Toronto','(GMT-8) Vancouver','(GMT-3) São Paulo']},{value:'Europe',items:['(GMT+0) London','(GMT+1) Paris','(GMT+1) Berlin','(GMT+1) Rome','(GMT+1) Madrid','(GMT+1) Amsterdam']},{value:'Asia/Pacific',items:['(GMT+9) Tokyo','(GMT+8) Shanghai','(GMT+8) Singapore','(GMT+4) Dubai','(GMT+11) Sydney','(GMT+9) Seoul']}]; countries=['Argentina','Australia','Brazil','Canada','China','Colombia','Egypt','France','Germany','Italy','Japan','Kenya','Mexico','New Zealand','Nigeria','South Africa','South Korea','United Kingdom','United States']"
data-example="combobox-clear combobox-disabled combobox-groups combobox-input-group combobox-invalid combobox-popup"
>
<main class="combobox-workflows visual-example">
<section class="combobox-workflow">
<div
id="clear-combobox"
ng-combobox
ng-on-angularcss:combobox-select="clearState.selected=$event.detail.value; clearState.query=$event.detail.value"
ng-on-angularcss:combobox-clear="clearState.selected=''; clearState.query=''"
>
<header>
<input
aria-label="Clearable framework"
ng-model="clearState.query"
placeholder="Select a framework"
/>
<button type="button" value="clear"></button>
</header>
<aside aria-label="Clearable framework options">
<p>No items found.</p>
<div>
<ul>
<li
ng-repeat="framework in frameworks | filter:clearState.query"
data-value="{{ framework }}"
ng-attr-aria-selected="{{ clearState.selected === framework }}"
>
{{ framework }}
</li>
</ul>
</div>
</aside>
</div>
</section>
<section class="combobox-workflow">
<div id="disabled-combobox" ng-combobox>
<header>
<input
aria-label="Disabled framework"
placeholder="Select a framework"
disabled
/>
<button
type="button"
aria-label="Show disabled frameworks"
disabled
value="toggle"
></button>
</header>
<aside aria-label="Disabled framework options">
<div>
<ul>
<li
ng-repeat="framework in frameworks"
data-value="{{ framework }}"
>
{{ framework }}
</li>
</ul>
</div>
</aside>
</div>
</section>
<section class="combobox-workflow">
<div
id="groups-combobox"
ng-combobox
ng-on-angularcss:combobox-select="grouped.selected=$event.detail.value; grouped.query=$event.detail.value"
>
<header>
<input
aria-label="Grouped timezone"
ng-model="grouped.query"
placeholder="Select a timezone"
/>
<button
type="button"
aria-label="Show grouped timezones"
value="toggle"
></button>
</header>
<aside aria-label="Grouped timezone options">
<p>No timezones found.</p>
<div>
<section
ng-repeat="group in timezoneGroups"
ng-if="(group.items | filter:grouped.query).length"
>
<h3>{{ group.value }}</h3>
<ul>
<li
ng-repeat="zone in group.items | filter:grouped.query"
data-value="{{ zone }}"
ng-attr-aria-selected="{{ grouped.selected === zone }}"
>
{{ zone }}
</li>
</ul>
<hr />
</section>
</div>
</aside>
</div>
</section>
<section class="combobox-workflow">
<div
id="input-group-combobox"
ng-combobox
ng-on-angularcss:combobox-select="inputGroupState.selected=$event.detail.value; inputGroupState.query=$event.detail.value"
>
<header>
<span class="combobox-globe" aria-hidden="true"></span>
<input
aria-label="Timezone with icon"
ng-model="inputGroupState.query"
placeholder="Select a timezone"
/>
<button
type="button"
aria-label="Show icon timezones"
value="toggle"
></button>
</header>
<aside
aria-label="Icon timezone options"
style="--combobox-options-width: 15rem"
>
<p>No timezones found.</p>
<div>
<section
ng-repeat="group in timezoneGroups"
ng-if="(group.items | filter:inputGroupState.query).length"
>
<h3>{{ group.value }}</h3>
<ul>
<li
ng-repeat="zone in group.items | filter:inputGroupState.query"
data-value="{{ zone }}"
>
{{ zone }}
</li>
</ul>
</section>
</div>
</aside>
</div>
</section>
<section class="combobox-workflow">
<div
id="invalid-combobox"
ng-combobox
ng-on-angularcss:combobox-select="invalidState.selected=$event.detail.value; invalidState.query=$event.detail.value"
>
<header>
<input
aria-label="Invalid framework"
aria-invalid="true"
ng-model="invalidState.query"
placeholder="Select a framework"
/>
<button
type="button"
aria-label="Show invalid frameworks"
value="toggle"
></button>
</header>
<aside aria-label="Invalid framework options">
<p>No items found.</p>
<div>
<ul>
<li
ng-repeat="framework in frameworks | filter:invalidState.query"
data-value="{{ framework }}"
>
{{ framework }}
</li>
</ul>
</div>
</aside>
</div>
</section>
<section class="combobox-workflow combobox-popup-workflow">
<div
id="popup-combobox"
ng-combobox
ng-on-angularcss:combobox-select="popup.selected=$event.detail.value; popup.query=''"
>
<button
type="button"
variant="outline"
aria-label="Country"
value="toggle"
>
<span ng-bind="popup.selected"></span>
</button>
<aside aria-label="Country options">
<header>
<input
aria-label="Search countries"
ng-model="popup.query"
placeholder="Search"
/>
</header>
<p>No items found.</p>
<div>
<ul>
<li
ng-repeat="country in countries | filter:popup.query"
data-value="{{ country }}"
ng-attr-aria-selected="{{ popup.selected === country }}"
>
{{ country }}
</li>
</ul>
</div>
</aside>
</div>
</section>
<output class="visually-hidden" aria-live="polite">
Clear: <span ng-bind="clearState.selected || 'none'"></span>. Grouped:
<span ng-bind="grouped.selected || 'none'"></span>. Popup:
<span ng-bind="popup.selected"></span>.
</output>
</main>
</body>
</html>
Custom, Multiple, And RTL
Custom option content and chip collections remain ordinary authored HTML and AngularTS application state.
View source
<!doctype html>
<html lang="en">
<head>
<meta charset="utf-8" />
<meta name="viewport" content="width=device-width, initial-scale=1" />
<title>AngularCSS Combobox Compositions</title>
<link rel="stylesheet" href="../../css/preflight.css" />
<link rel="stylesheet" href="../../css/angular.css" />
<link rel="stylesheet" href="../example.css" />
<script src="../../js/angular-ts.umd.js"></script>
<script src="../../js/angular-css.umd.js"></script>
</head>
<body
ng-app="angular.css"
ng-cloak
ng-init="frameworks=['Next.js','SvelteKit','Nuxt.js','Remix','Astro']; custom={query:'',selected:''}; multi={query:'',next:true,svelte:false,nuxt:false,remix:false,astro:false}; rtl={query:'',technology:true,design:false,business:false,marketing:false,education:false,health:false}; countries=[{code:'ar',label:'Argentina',continent:'South America'},{code:'au',label:'Australia',continent:'Oceania'},{code:'br',label:'Brazil',continent:'South America'},{code:'ca',label:'Canada',continent:'North America'},{code:'cn',label:'China',continent:'Asia'},{code:'co',label:'Colombia',continent:'South America'},{code:'eg',label:'Egypt',continent:'Africa'},{code:'fr',label:'France',continent:'Europe'},{code:'de',label:'Germany',continent:'Europe'},{code:'it',label:'Italy',continent:'Europe'},{code:'jp',label:'Japan',continent:'Asia'},{code:'ke',label:'Kenya',continent:'Africa'},{code:'mx',label:'Mexico',continent:'North America'},{code:'nz',label:'New Zealand',continent:'Oceania'},{code:'ng',label:'Nigeria',continent:'Africa'},{code:'za',label:'South Africa',continent:'Africa'},{code:'kr',label:'South Korea',continent:'Asia'},{code:'gb',label:'United Kingdom',continent:'Europe'},{code:'us',label:'United States',continent:'North America'}]; categories=['التكنولوجيا','التصميم','الأعمال','التسويق','التعليم','الصحة']"
data-example="combobox-custom combobox-multiple combobox-rtl"
>
<main class="combobox-compositions visual-example">
<section class="combobox-composition">
<div
id="custom-combobox"
ng-combobox
ng-on-angularcss:combobox-select="custom.selected=$event.detail.value; custom.query=$event.detail.value"
>
<header>
<input
aria-label="Country with details"
ng-model="custom.query"
placeholder="Search countries..."
/>
<button
type="button"
aria-label="Show detailed countries"
value="toggle"
></button>
</header>
<aside aria-label="Detailed country options">
<p>No countries found.</p>
<div>
<ul>
<li
ng-repeat="country in countries | filter:custom.query"
data-value="{{ country.label }}"
ng-attr-aria-selected="{{ custom.selected === country.label }}"
>
<article size="xs" class="combobox-custom-item item">
<section>
<h3>{{ country.label }}</h3>
<p>{{ country.continent }} ({{ country.code }})</p>
</section>
</article>
</li>
</ul>
</div>
</aside>
</div>
</section>
<section class="combobox-composition">
<div
id="multiple-combobox"
ng-combobox
multiple
auto-highlight
ng-on-angularcss:combobox-select="$event.detail.value === 'Next.js' ? multi.next=!multi.next : $event.detail.value === 'SvelteKit' ? multi.svelte=!multi.svelte : $event.detail.value === 'Nuxt.js' ? multi.nuxt=!multi.nuxt : $event.detail.value === 'Remix' ? multi.remix=!multi.remix : multi.astro=!multi.astro"
ng-on-angularcss:combobox-remove-last="multi.astro ? multi.astro=false : multi.remix ? multi.remix=false : multi.nuxt ? multi.nuxt=false : multi.svelte ? multi.svelte=false : multi.next=false"
>
<fieldset>
<span ng-if="multi.next" animate>
Next.js
<button
type="button"
aria-label="Remove Next.js"
ng-click="multi.next=false"
value="remove"
></button>
</span>
<span ng-if="multi.svelte" animate>
SvelteKit
<button
type="button"
aria-label="Remove SvelteKit"
ng-click="multi.svelte=false"
value="remove"
></button>
</span>
<span ng-if="multi.nuxt" animate>
Nuxt.js
<button
type="button"
aria-label="Remove Nuxt.js"
ng-click="multi.nuxt=false"
value="remove"
></button>
</span>
<span ng-if="multi.remix" animate>
Remix
<button
type="button"
aria-label="Remove Remix"
ng-click="multi.remix=false"
value="remove"
></button>
</span>
<span ng-if="multi.astro" animate>
Astro
<button
type="button"
aria-label="Remove Astro"
ng-click="multi.astro=false"
value="remove"
></button>
</span>
<input
aria-label="Frameworks"
ng-model="multi.query"
placeholder="Add framework"
/>
</fieldset>
<aside aria-label="Multiple framework options">
<p>No items found.</p>
<div>
<ul>
<li
ng-repeat="framework in frameworks | filter:multi.query"
data-value="{{ framework }}"
ng-attr-aria-selected="{{ framework === 'Next.js' ? multi.next : framework === 'SvelteKit' ? multi.svelte : framework === 'Nuxt.js' ? multi.nuxt : framework === 'Remix' ? multi.remix : multi.astro }}"
>
{{ framework }}
</li>
</ul>
</div>
</aside>
</div>
</section>
<section
class="combobox-composition combobox-rtl-composition"
lang="ar"
dir="rtl"
>
<div class="field">
<label for="rtl-combobox-input">الفئات</label>
<div
id="rtl-combobox"
ng-combobox
multiple
auto-highlight
ng-on-angularcss:combobox-select="$event.detail.value === 'التكنولوجيا' ? rtl.technology=!rtl.technology : $event.detail.value === 'التصميم' ? rtl.design=!rtl.design : $event.detail.value === 'الأعمال' ? rtl.business=!rtl.business : $event.detail.value === 'التسويق' ? rtl.marketing=!rtl.marketing : $event.detail.value === 'التعليم' ? rtl.education=!rtl.education : rtl.health=!rtl.health"
ng-on-angularcss:combobox-remove-last="rtl.health ? rtl.health=false : rtl.education ? rtl.education=false : rtl.marketing ? rtl.marketing=false : rtl.business ? rtl.business=false : rtl.design ? rtl.design=false : rtl.technology=false"
>
<fieldset>
<span ng-if="rtl.technology" animate>
التكنولوجيا
<button
type="button"
aria-label="إزالة التكنولوجيا"
ng-click="rtl.technology=false"
value="remove"
></button>
</span>
<span ng-if="rtl.design" animate>
التصميم
<button
type="button"
aria-label="إزالة التصميم"
ng-click="rtl.design=false"
value="remove"
></button>
</span>
<span ng-if="rtl.business" animate>
الأعمال
<button
type="button"
aria-label="إزالة الأعمال"
ng-click="rtl.business=false"
value="remove"
></button>
</span>
<span ng-if="rtl.marketing" animate>
التسويق
<button
type="button"
aria-label="إزالة التسويق"
ng-click="rtl.marketing=false"
value="remove"
></button>
</span>
<span ng-if="rtl.education" animate>
التعليم
<button
type="button"
aria-label="إزالة التعليم"
ng-click="rtl.education=false"
value="remove"
></button>
</span>
<span ng-if="rtl.health" animate>
الصحة
<button
type="button"
aria-label="إزالة الصحة"
ng-click="rtl.health=false"
value="remove"
></button>
</span>
<input
id="rtl-combobox-input"
aria-label="الفئات"
ng-model="rtl.query"
placeholder="أضف فئات"
/>
</fieldset>
<aside lang="ar" aria-label="خيارات الفئات">
<p>لم يتم العثور على فئات.</p>
<div>
<ul>
<li
ng-repeat="category in categories | filter:rtl.query"
data-value="{{ category }}"
ng-attr-aria-selected="{{ category === 'التكنولوجيا' ? rtl.technology : category === 'التصميم' ? rtl.design : category === 'الأعمال' ? rtl.business : category === 'التسويق' ? rtl.marketing : category === 'التعليم' ? rtl.education : rtl.health }}"
>
{{ category }}
</li>
</ul>
</div>
</aside>
</div>
</div>
</section>
<output class="visually-hidden" aria-live="polite">
Country: <span ng-bind="custom.selected || 'none'"></span>. Frameworks:
<span ng-bind="multi.next ? 'Next.js' : 'none'"></span>. Categories:
<span ng-bind="rtl.technology ? 'التكنولوجيا' : 'none'"></span>.
</output>
</main>
</body>
</html>
Controlled State
The state artifact covers controlled disclosure, disabled-option skipping, Home and End navigation, dynamic options, and outside dismissal.
View source
<!doctype html>
<html lang="en">
<head>
<meta charset="utf-8" />
<meta name="viewport" content="width=device-width, initial-scale=1" />
<title>AngularCSS Combobox State Workflows</title>
<link rel="stylesheet" href="../../css/preflight.css" />
<link rel="stylesheet" href="../../css/angular.css" />
<link rel="stylesheet" href="../example.css" />
<script src="../../js/angular-ts.umd.js"></script>
<script src="../../js/angular-css.umd.js"></script>
</head>
<body
ng-app="angular.css"
ng-cloak
ng-init="state={query:'',selected:'Next.js',open:false,showAstro:false}; stateOptions=[{label:'Next.js',disabled:false},{label:'SvelteKit',disabled:true},{label:'Nuxt.js',disabled:false},{label:'Remix',disabled:false}]"
>
<main class="combobox-state-workflows visual-example">
<div class="combobox-state-controls">
<button
type="button"
variant="outline"
ng-click="state.open=!state.open"
>
Toggle popup
</button>
<button
type="button"
variant="outline"
ng-click="state.showAstro=!state.showAstro"
>
Toggle Astro option
</button>
</div>
<div
id="state-combobox"
ng-combobox
auto-highlight
open="{{ state.open }}"
ng-on-angularcss:combobox-open-change="state.open=$event.detail.open"
ng-on-angularcss:combobox-select="state.selected=$event.detail.value; state.query=$event.detail.value; state.open=false"
>
<header>
<input
aria-label="State framework"
ng-model="state.query"
placeholder="Select a framework"
/>
<button
type="button"
aria-label="Show state frameworks"
value="toggle"
></button>
</header>
<aside aria-label="State framework options">
<p>No items found.</p>
<div>
<ul>
<li
ng-repeat="option in stateOptions | filter:state.query"
data-value="{{ option.label }}"
ng-attr-aria-disabled="{{ option.disabled }}"
ng-attr-aria-selected="{{ state.selected === option.label }}"
>
{{ option.label }}
</li>
<li
ng-if="state.showAstro"
data-value="Astro"
ng-attr-aria-selected="{{ state.selected === 'Astro' }}"
>
Astro
</li>
</ul>
</div>
</aside>
</div>
<output class="combobox-state-output" aria-live="polite">
Selected: <span ng-bind="state.selected"></span>. Popup:
<span ng-bind="state.open ? 'open' : 'closed'"></span>. Astro:
<span ng-bind="state.showAstro ? 'shown' : 'hidden'"></span>.
</output>
</main>
</body>
</html>
Installation
Install AngularCSS, load its stylesheet, and include the angular.css module in your AngularTS application. See Installation for the complete setup.
This component’s root directive is [ng-combobox]. Importing the package registers it with the AngularCSS angular.css module; there is no per-component JavaScript registration step.
Anatomy
Directive selectors
ng-combobox
Semantic structure
A combobox root requires one input and one options surface. The root directive inspects semantic headers, sections, lists, options, fieldsets, and buttons; no child directives or anatomy classes are required.
API
Attributes and state
| Attribute | Access | Purpose |
|---|---|---|
aria-activedescendant | Output | ID of the active option while focus remains on the composite control. |
aria-autocomplete | Input/output | How a text control presents completion suggestions. |
aria-controls | Output | ID of the element controlled by a trigger. |
aria-disabled | Input/output | Semantic disabled state. |
aria-expanded | Output | Open or expanded state exposed to assistive technology. |
aria-haspopup | Output | Type of popup controlled by the trigger. |
aria-hidden | Input/output | Whether generated or collapsed content is hidden from assistive technology. |
aria-invalid | Input | Validation state exposed to assistive technology and CSS. |
aria-label | Input/output | Accessible name when visible text is insufficient. |
aria-labelledby | Output | ID of the element that supplies the accessible name. |
aria-multiselectable | Output | Whether the composite allows multiple selected items. |
aria-orientation | Output | Interaction axis exposed to assistive technology. |
aria-selected | Input/output | Selected item state. |
auto-highlight | Input | Highlights the first enabled result when the popup opens or filters change. |
data-highlighted | Output | Current option highlighted for keyboard selection. |
data-value | Input | Application value reported when the corresponding option is selected. |
dir | Input | Text and interaction direction: ltr or rtl. |
disabled | Input | Disables native or component interaction. |
hidden | Input | Native visibility state observed when finding available items. |
multiple | Input | Keeps the popup open and reports selections for an application-owned collection. |
open | Input/output | Initial or externally synchronized disclosure state. |
required | Input | Marks a native form value as required. |
role | Output | Explicit semantic role when native HTML does not provide one. |
side | Output | Physical placement: left, top, bottom, or right. |
tabindex | Output | Keyboard focus order for composite descendants. |
Input attributes are read from authored HTML. Output attributes are maintained by AngularCSS for CSS and testing. Input/output attributes may be authored for a controlled initial state and are then synchronized by the directive.
CSS custom properties
| Variable | Purpose |
|---|---|
--combobox-anchor-width | Component styling variable. |
--combobox-content-top | Component styling variable. |
DOM events
angularcss:combobox-clearangularcss:combobox-open-changeangularcss:combobox-remove-lastangularcss:combobox-select
Native DOM events continue to work normally. AngularTS event directives such as
ng-click and ng-keydown, plus the data-change model callback, remain application-owned.
Behavior
The directive owns disclosure, collision-aware placement, active-descendant navigation, enabled-option boundaries, Escape and outside dismissal, and selection, clear, remove-last, and open-change signaling. AngularTS remains responsible for query filtering, selected values and collections, controlled open state, validation, and structural bindings such as ng-repeat, ng-if, and ng-model.
AngularCSS does not replace AngularTS interpolation, bindings, structural directives, form controllers, validation, or application state.
Accessibility
Give the input an accessible name. The input exposes combobox, expanded, controls, autocomplete, invalid, disabled, and active-descendant state connected to a listbox. Arrow keys, Home, End, Enter, Escape, and Tab operate on enabled visible options; labeled groups retain group relationships, multiple listboxes expose aria-multiselectable, and text direction is mirrored to the popup.
Authored accessible names and relationships are preserved. Test the final composition with keyboard navigation and assistive technology because labels and content come from the application.
Customization
Target [ng-combobox], semantic descendants, component classes, and generated state with ordinary CSS. Keep behavior and accessible state in the TypeScript directive; visual choices belong in the application stylesheet.
Read Customization for layer order, design tokens, state variants, and iframe demo isolation.
Feedback
Was this page helpful?
Glad to hear it! Please tell us how we can improve.
Sorry to hear that. Please tell us how we can improve.