aria-describedby passthrough for hint and error text — the same shape of gap as the name.
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.
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.
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.
ReadonlyNamedThis instance's id suffix, shared by every id the control generates.
Static ReadonlyGenericThe placeholder a caller gets by having said nothing — it names no particular search.
Use Focused.
PlaceholderIsName is passed here and nowhere else: this is a toolbar widget whose placeholder
("Search templates…") IS the caller's statement of what the box searches. On a form control a
placeholder is not a name — it disappears as soon as the user types — so those controls warn
without one.
It is not passed unconditionally, or the guard could never fire here at all: the default
placeholder is non-empty, so accepting any placeholder would accept 'Search...', which tells a
screen-reader user nothing about what is being searched. Only a placeholder the caller actually
chose counts.
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.
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.
Id of a hidden span holding one fixed WORD of a secondary control's name — "Filter", "Clear", "Open calendar for". Composed with the host's visible label by SecondaryLabelledBy.
mj-page-search — Canonical in-page search input for dashboard headers and toolbars. Replaces per-page
.search-input-wrapperrules so styling can't drift.Distinct from
mj-search-input(the navbar/global search in@memberjunction/ng-search) — this one is a simple text input used for filtering page content.The
Placeholderis the accessible name of last resort — it is what the name computation falls back to, and it disappears the moment the user types. Pass MJNamedControlBase.AriaLabel (or MJNamedControlBase.AriaLabelledBy when a visible label exists) so the box has a name that survives having text in it. The control is a real<input>, so MJNamedControlBase.InputId IS a valid<label for>target.Example: