Skip to content

Company Picker Design

Ed Mozley edited this page Nov 15, 2026 · 1 revision

🏒 Many companies: searchable company lists - design

Issue #358, asked by @pappas81 (an IT support company with about 3,000 clients) Β· 5.4.0 Β· User help: System β†’ Help β†’ Companies β†’ Many companies: searching the lists

The problem

Every place FreeITSM asks "which company?" was a plain <select> - about 45 of them across 30 screens, each filling its own list, with no shared component. At 3,000 companies a plain list cannot be used, and the header's company switcher printed one button per company into every page.

Decided

Date Question Decision
16 Nov 2026 How far for 5.4.0? Everywhere (Ed): every company dropdown, the header switcher, the right-click Move to company menus and the company tick-lists.
16 Nov 2026 Always a search box, or only when long? Past a number set in System β†’ Companies β†’ Company lists (default 15; 0 = always). A small install sees no change - the request's own words were "of course make it an option".
16 Nov 2026 How many results? 10 at a time, with Showing 10 of 2,987 - type to narrow, as asked.

How it works

assets/js/select-search.js upgrades a <select> whose id or name mentions company or tenant, or that carries data-searchable, once it has more options than the setting. The real <select> stays, hidden by a class, and keeps the value - the same trick as the date picker - so no screen was rewritten:

  • a pick sets select.value and fires input and change, so every existing handler runs;
  • code that sets value or selectedIndex is followed (the two are overridden on that one element);
  • options filled in or replaced later are followed (a MutationObserver), so a list loaded by fetch after the page opens is upgraded when it arrives;
  • code that hides the select (style.display, hidden) or disables it is mirrored on the box.

Not upgraded: a multiple select, and anything inside data-native-select.

FreeitsmSelectSearch.filterList(container, itemSelector, {cap}) does the same for lists that are not <select>s: a search box at the top of a right-click submenu (cap 10, Enter picks the first) or a list of tickboxes (no cap, so every tick stays reachable; Enter ticks nothing).

Loaded by the header's company switcher (includes/tenancy-switcher.php), not by Tz::scriptTag(): the switcher is on every analyst page with a header, and only once a second company exists - which is exactly when a company list can be long. (Several pages with company lists do not call Tz::scriptTag().) The switcher itself, past the setting, shows a search box and the current company, and fetches the company list from api/system/get_tenants.php?accessible=1 the first time someone types - never one button per company in every page. Its words were English only; they are translated now.

🎨 File What
🧠 assets/js/select-search.js The upgrade and filterList()
πŸ”Œ api/system/company_list_settings.php The setting (company_list_search_after), administrators only
πŸ–₯️ system/companies/index.php The Company lists card
πŸ–₯️ includes/tenancy-switcher.php Loads the script; the switcher's own search
πŸ–₯️ assets/js/inbox.js, change-management.js, tasks-ctx-menu.js filterList() on the Move to company submenus
πŸ–₯️ system/analysts, system/teams, system/api, system/companies, assets/js/ticket-type-rules.js filterList() on the tick-lists
🏷️ tickets/settings (priority scope), asset-management (Key info), report-packs/designer.js data-searchable - company lists whose id does not say so
πŸ§ͺ tests/select-search.php 34 checks in headless Chrome; SELECT_SEARCH_CONTROL=1 runs without the script and fails

Not done, deliberately

  • Per-company tables (Tickets settings per-company columns, Tasks contractor fields, issue-tracker project mapping) list every company as rows. They are not pickers; at 3,000 companies they want paging, which is a separate change.
  • System β†’ Companies' own list renders every company; it has its own search box already.

See also: Companies Β· Date picker - design

FreeITSM

Getting Started

Modules

Multi-tenancy (planned)

Responses to feedback

Blue sky thinking

Bugs resolved

Pull requests

Links

Clone this wiki locally