Member Junction
    Preparing search index...

    mj-dropdown — Dropdown select component using CDK Overlay.

    Replaces <kendo-dropdownlist>.

    Every dropdown needs an ACCESSIBLE NAME, or it announces as "combobox, collapsed" with no hint of what it selects (WCAG 2.1 4.1.2). Use AriaLabelledBy when a visible label already exists — <label for> cannot name a div[role=combobox] — and AriaLabel when none does.

    Escape with the list open closes the list and goes no further, so a dialog or popover around the field stays open. With the list closed, Escape goes on to the host as usual.

    <span id="persona-label">Interview persona</span>
    <mj-dropdown
    AriaLabelledBy="persona-label"
    [Data]="items"
    TextField="name"
    ValueField="id"
    [(ngModel)]="selectedId"
    [ValuePrimitive]="true">
    </mj-dropdown>
    <mj-dropdown
    AriaLabel="Interview persona"
    [Data]="items"
    TextField="name"
    ValueField="id"
    [(ngModel)]="selectedId"
    [ValuePrimitive]="true"
    [Filterable]="true"
    (FilterChange)="onFilter($event)">
    </mj-dropdown>

    Hierarchy (View Summary)

    Implements

    • ControlValueAccessor
    • AfterViewInit
    • OnDestroy
    Index

    Constructors

    Properties

    AriaDescribedBy: string = ''

    aria-describedby passthrough for hint and error text — the same shape of gap as the name.

    AriaLabel: string = ''

    Accessible name for the control, for when no visible label exists. Prefer AriaLabelledBy when one does — an aria-label duplicates that label's text and drifts from it on rename. aria-labelledby beats aria-label where both are present.

    AriaLabelledBy: string = ''

    The id of a VISIBLE label element that names this control — the preferred wiring whenever a label already exists on screen. It is also the only path that can name a control's SECONDARY pieces (a filter box, a toggle, a calendar) from that same label: see SecondaryLabelledBy.

    Data: string[] | Record<string, unknown>[] | readonly unknown[] | null = []
    DefaultItem: string | Record<string, unknown> | null = null
    DropdownId: number = ...

    This dropdown's id suffix — the shared named-control counter, kept under its own name.

    Filterable: boolean = false
    FilterChange: EventEmitter<string> = ...
    filterText: string = ''
    HighlightedIndex: number = -1
    hostClass: true
    InputId: string = ''

    id for the control's focusable element, so other markup can REFERENCE it — aria-controls, hint text, test hooks.

    Whether it doubles as a <label for> target depends on the control, because label[for] associates only with LABELABLE elements: it works on the input-backed controls (mj-combobox, mj-numeric-input, mj-datepicker, mj-page-search) and on mj-switch, whose <button> is labelable too. It does NOT work on mj-dropdown, whose trigger is a div[role=combobox] — wiring label[for] there produces markup that looks correct, passes review, and leaves the control named only in the browsers that guess. Each control's own docs say which it is.

    IsDisabled: boolean = false

    The single gate on Toggle() / Open() — true when EITHER the Disabled input or Angular Forms says so. Never assign it directly; go through syncDisabled() so both sources are always composed and a lock closes an open panel.

    IsOpen: boolean = false
    ItemTemplate: TemplateRef<{ $implicit: unknown }> | null = null
    NamedControlId: number = ...

    This instance's id suffix, shared by every id the control generates.

    Placeholder: string = 'Select...'
    Positions: ConnectedPosition[] = ...
    SelectedValue: unknown = null
    TextField: string = ''
    TriggerWidth: number = 0
    ValueChange: EventEmitter<unknown> = ...
    ValueField: string = ''
    ValuePrimitive: boolean = false

    Accessors

    Methods

    • Keys pressed in the field or in the filter box. Escape with the list open closes the list and stops the key there (see closeListOnEscape). With the list closed, Escape is cancelled as before and goes on to the host, so a dialog or popover around the field still closes on it.

      Parameters

      • event: KeyboardEvent

      Returns void

    • Keys the open list's overlay receives. The overlay listens on the page body, so this sees a key that did not go through the field or the filter box, for example after a click inside the panel moved focus to the page. Escape closes the list here too, by the same rule as OnKeyDown; other keys are left alone.

      Parameters

      • event: KeyboardEvent

      Returns void

    • Parameters

      • fn: (value: unknown) => void

        The callback function to register

      Returns void

      Registers a callback function that is called when the control's value changes in the UI.

      This method is called by the forms API on initialization to update the form model when values propagate from the view to the model.

      When implementing the registerOnChange method in your own value accessor, save the given function so your class calls it at the appropriate time.

      The following example stores the provided function as an internal method.

      registerOnChange(fn: (_: any) => void): void {
      this._onChange = fn;
      }

      When the value changes in the UI, call the registered function to allow the forms API to update itself:

      host: {
      '(change)': '_onChange($event.target.value)'
      }
    • Parameters

      • fn: () => void

        The callback function to register

      Returns void

      Registers a callback function that is called by the forms API on initialization to update the form model on blur.

      When implementing registerOnTouched in your own value accessor, save the given function so your class calls it when the control should be considered blurred or "touched".

      The following example stores the provided function as an internal method.

      registerOnTouched(fn: any): void {
      this._onTouched = fn;
      }

      On blur (or equivalent), your class should call the registered function to allow the forms API to update itself:

      host: {
      '(blur)': '_onTouched()'
      }
    • aria-label for a secondary control in the no-visible-label case: word followed by the host's own name, or fallback when the host has no name either.

      The already-starts-with-word guard is not cosmetic: this repo's house habit is AriaLabel="Filter roles", and an unconditional prefix announces that box as "Filter Filter roles".

      The match ends on a WORD BOUNDARY, not on a space: AriaLabel="Filter: roles" already begins with the word and must not be prefixed either, while "Filters" is a different word and must be. A space-only test gets the punctuated case wrong in the doubling direction.

      Parameters

      • word: string
      • fallback: string

      Returns string

    • aria-labelledby for a secondary control when a VISIBLE label names the host: the hidden word plus that label's own text, composed by the accessibility tree from an id LIST. Empty when there is no such label, in which case SecondaryLabel supplies a string instead.

      An id list is the only mechanism that can work here — the component never sees the label's text, only its id. Without it, every filterable dropdown on a form named this way announces an identical "Filter options", and a form with six of them has six indistinguishable filter boxes.

      Parameters

      • slug: string

      Returns string

    • Parameters

      • isDisabled: boolean

        The disabled status to set on the element

      Returns void

      Function that is called by the forms API when the control status changes to or from 'DISABLED'. Depending on the status, it enables or disables the appropriate DOM element.

      The following is an example of writing the disabled property to a native DOM element:

      setDisabledState(isDisabled: boolean): void {
      this._renderer.setProperty(this._elementRef.nativeElement, 'disabled', isDisabled);
      }
    • Parameters

      • value: unknown

      Returns void

      Writes a new value to the element.

      This method is called by the forms API to write to the view when programmatic changes from model to view are requested.

      The following example writes a value to the native DOM element.

      writeValue(value: any): void {
      this._renderer.setProperty(this._elementRef.nativeElement, 'value', value);
      }