2a. Default trigger: count summary
markup
Example directives, not a supported wrapper. Copy
llselect-angularjs.js (or llselect-ui-select.js)
into your project and adapt it. The reasoning, the source references, and
the list of deliberate gaps are in
angularjs/README.md.
Run npm run build, then npm run serve:site, and open
/demo/angularjs/examples.html. AngularJS itself comes from a CDN; nothing
AngularJS-related is in the package.
ll-options takes an ng-options expression. Every
clause maps onto an llselect setting; see the table in the README.
The trigger has two displays: the default 'count' summary and
ll-trigger-display="'tags'" chips. Rows carry live checkbox
icons by default (ll-checkboxes="false" opts out), and
ll-choose-all-row="true" adds the tri-state row acting on the
visible enabled subset.
ll-checkboxes (default true) draws SVG checkboxes on the
rows and this row; ll-checkboxes="false" strips them all,
leaving plain text - which is also the core's own default (core demo
5.7).
Chosen items leave the popup; removing a tag puts them back, and the
clear button puts everything back at once. Pairs with the tags trigger,
and with ll-checkboxes="false" - a listed row here is
always unchecked, so checkboxes would say nothing.
The point of this page. myForm.fruit resolves because
AngularJS reads name off this element as a plain
attribute - there is no native <select> and no hidden
input anywhere. Clear the selection to watch the form go invalid.
select as is the ngModel value projection. llselect has no
equivalent setting on purpose - the app declares it, exactly as
ng-options does.
Setting attributes are read once at construction; ll-disabled gets
a $watch because it maps onto the setDisabled() method.
ll-arrow takes llselect's two built-in arrows and nothing
else; a custom one means editing your copy of the file. The house style
comes from llselectConfigProvider in .config()
(see app.js) - this demo sets arrow: 'chevron'
app-wide, which is why the selects above have one without saying so. A
per-element ll-arrow wins over it.
An expression evaluating to a function (item) => HTMLElement | null,
passed straight to llselect's createItemContentElFn. It runs
per rendered row per render, outside any digest, and the element is never
$compiled - custom rows with zero per-row scope or watcher.
The accessible name and filter text stay the item text from
ll-options (icons and hints never reach a screen reader).
All renderers are in
app.js. For real per-row Angular templates, that is
<ui-llselect> below.
renderLangRow builds the row with createElement;
feeding the SAME renderer to ll-trigger-content-fn is what
makes the trigger show the chosen row - there is no auto-projection.
renderLangRowFromTpl clones the <template>
and fills it - the row markup lives in HTML, still with no scope and no
$compile. On a multiple the element renders beside the
default checkbox.
renderUserRow: primary text plus a faded hint pushed to the
row's right edge (.user-row), with disable when
dimming suspended users on top. The name highlights the filter match
via the core createHighlightedTextEl (7f's pattern).
ONE renderer feeds rows AND chips (ll-tag-content-fn);
ll-tag-remove-button-content-fn swaps the remove icon, else
the theme's CSS glyph draws the x.
What <option style="background-color"> does on a
native select (Chromium only): renderTintedLangRow is 7a's
row tinted from its icon color, with createCheckmarkSvgEl
on the chosen row (rows re-render on chosen changes - never stale).
All inline styles, plus one demo CSS line (lang-tinted)
zeroing the option element's padding. The whole trigger takes the
chosen colors: demo-tint-trigger requires the published
controller and paints instance().triggerEl (API.md
"Reaching the instance from your own directive").
ll-highlight="true" wraps each query match in the default
item text in <mark> (the core
createHighlightedTextEl); the marks follow the typing.
With a custom ll-item-content-fn call the helper yourself,
the way 7c does.
A separate directive (llselect-ui-select.js, module
llselect.uiCompat) that takes
ui-select's
call-site markup, so an existing ui-select codebase can migrate without
rewriting every call site. New code should use
<llselect-single> /
<llselect-multiple> above instead.
Migrating a call site: rename the elements
(ui-select family to ui-llselect family) and
add ll-item-text - ui-select has no item-to-string concept,
and llselect needs one for the option's accessible name. The template
content carries over untouched. CSS does not - llselect owns the DOM, so
this is styled by the llselect theme.
As in real ui-select, a chosen person leaves the dropdown:
remove-selected defaults to true (8g shows the opt-out).
The template has three shapes: elements (above), a bare text node, or
none at all - rows then render the ll-item-text string
itself, which ui-select cannot do (its template is its only source of
item text).
The | filter: chain IS the custom filter, re-evaluated once
per typed query. Try vlan2 - the ifaceMatch
filter (app.js) ignores spaces.
Interop with uib-tooltip from
angular-ui-bootstrap
- the component kit most AngularJS apps already carry: both directives
sit on the same element, no conflict. ng-disabled carries
over here (ui-select parity, via attrs.$observe; the main
directives use ll-disabled). The attribute is inert on
this host, so hover works in BOTH states - the tooltip keeps working
while disabled, which a native disabled control forbids.
Top: the default. A chosen person leaves the list, exactly like
ui-select (remove-selected defaults to true; bridged onto
hideChosenRows). Its allow-clear puts everyone
back at once - the deviation the API page documents. Bottom:
remove-selected="false" keeps chosen rows listed.
Not bridged, by rule (llselect has no such concept, so it is ignored rather than half-implemented): tagging, sortable, append-to-body, async refresh, limit, themes.
A third-party validation library, included because it is the case that
started this: it throws unless the field has a name
(validation-common.js:460). It reads that name off the
ng-model element like everything else in AngularJS, so it
needs no native <select> either. Its
validation directive is restrict: 'A',
require: 'ngModel', and it revalidates from a watch on
ctrl.$modelValue - all element-agnostic.
Three integration facts worth knowing: it hard-depends on
pascalprecht.translate; its messages need
$translateProvider pointed at its locale files or you get
"Could not translate: 'INVALID_REQUIRED'"; and validation is debounced by
typingLimit (default 1000 ms), so it is not instant. Its
elm.bind('blur') trigger is inert here - blur does not bubble
and the focusable element is llselect's inner trigger - but the
$modelValue watch is the path that matters for a select.
Native <label for> cannot target these divs.
ll-label-el points at your label's id: the label names the
field, and clicking it focuses the trigger - focus only, like a native
label. (Core demo 12, as an attribute.)
Items are {interfaceType: 'vlan', interfaceNo: '2'}, shown
as VLAN 2. The default filter matches the shown text
(vlan 2 works out of the box); the custom fn also matches
the space-less vlan2.
The whole of what this page loads. Nothing is generated and nothing is minified: this is the file you copy.