shivaansh0610-LUFFY opened a new pull request, #637:
URL: https://github.com/apache/fineract-backoffice-ui/pull/637
<!--
Licensed to the Apache Software Foundation (ASF) under one
or more contributor license agreements. See the NOTICE file
distributed with this work for additional information
regarding copyright ownership. The ASF licenses this file
to you under the Apache License, Version 2.0 (the
"License"); you may not use this file except in compliance
with the License. You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing,
software distributed under the License is distributed on an
"AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
KIND, either express or implied. See the License for the
specific language governing permissions and limitations
under the License.
-->
<!-- Commits must be signed to merge — see CONTRIBUTING.md#commit-signing if
you haven't set this up. -->
## What and why
`ion-select`'s `popover`/`alert` interfaces have no filter field, so an
API-backed list — currencies, offices, GL accounts, and similar — forces the
user to scroll and read every entry to find one. Products → Collateral
Management → Create → Currency is the issue's own reproduction case: a
hundred-plus currencies, alphabetical, with nothing to type into.
This adds `app-searchable-select` under `src/app/ui/searchable-select/` and
wires it into that Currency field. Opening the control presents an `ion-modal`
with an `ion-searchbar` that filters by a case-insensitive substring of the
option label, an `aria-live` result count, and a "no results" state instead of
an empty panel.
It implements `ControlValueAccessor` directly rather than wrapping
`ion-select`, so `[(ngModel)]`, `name`, `required` and `disabled` work
unchanged at a call site — swapping one in is a template change, not a form
rewrite.
This is intentionally a pragmatic first cut, not ADR 0005's full dual
reactive-forms/`ngModel` CVA contract suite. It also migrates only the issue's
reproduction route; #626 catalogues roughly 111 files and 563 `ion-select` tags
across currency, office, client, staff and GL-account pickers, so the remaining
call sites are incremental follow-up, per the issue's own suggested rollout —
this PR does not close it.
Refs #626
## Verification
- `npm run lint` — clean.
- `npm run test:unit` — 252 files / 1586 tests passing, including 10 new
tests in `searchable-select.component.test.ts` covering the CVA contract,
filtering, selection, disabled/required behavior, and blur/touched wiring.
- `npm run build` — clean.
- `npm run i18n:check` — clean.
- `npm run check:a11y-names` — clean.
- `npm run check:icons` — clean.
- `npm run typecheck:e2e` — clean.
- `npx playwright test --project=mocked
e2e/collateral-currency-search.spec.ts` — 5/5 passing. Mocked rather than
against a real Fineract, since the new behavior is entirely client-side
filtering over data the existing template endpoint already returns.
- Exercised manually in the browser against mocked data: opening the field,
typing to filter, selecting a result, and the empty/cancel states.
## Screenshots
**Before** — the Currency `ion-select` opens a popover with no filter field;
finding a currency means scrolling and reading every entry.
<img width="1280" height="720" alt="currency-before-1-open-no-search"
src="https://github.com/user-attachments/assets/c368708b-7404-48d9-8401-a85437a75431"
/>
<img width="1280" height="720" alt="currency-before-2-scrolled-to-inr"
src="https://github.com/user-attachments/assets/7da30ef6-ba15-416b-bc7f-fff50d674eb7"
/>
<img width="1280" height="720" alt="currency-before-3-selected"
src="https://github.com/user-attachments/assets/9c2c4956-1287-40a6-92c3-52b40cb01d7c"
/>
[currency-before.webm](https://github.com/user-attachments/assets/2d01eaff-5cb0-4a0f-9dd6-13963b028fa1)
**After** — the new searchable select opens a modal with a search field
front and center; typing `rupee` immediately filters the list to the matching
option.
<img width="1280" height="720" alt="currency-after-1-open-with-search"
src="https://github.com/user-attachments/assets/65417d8d-eb2a-4855-a6d0-3a0f045bac6f"
/>
<img width="1280" height="720" alt="currency-after-2-filtered-inr"
src="https://github.com/user-attachments/assets/872d93b2-c846-4c7e-9a89-3ea5e92658c7"
/>
<img width="1280" height="720" alt="currency-after-3-selected"
src="https://github.com/user-attachments/assets/290f8ba5-1f21-4c65-b7ca-d922f6d21d2b"
/>
[currency-after.webm](https://github.com/user-attachments/assets/c388198a-22a0-46d8-b0fd-271293cc595a)
Originals are saved locally at
`~/Downloads/fineract-626-searchable-select/{before,after}/`.
## AI assistance (optional)
<!-- If generative AI materially assisted this contribution, optionally
state the tool or model and
the harness or workflow used. The contributor remains responsible for the
submitted change. -->
- Tool / model: Claude Sonnet 5
- Harness / workflow: Claude Code — implementation, test authoring,
verification, and the before/after Playwright recordings, run interactively in
the terminal.
## Checklist
<!-- Check each item, or explain why it does not apply. -->
- [x] I did not hand-edit generated files under `src/app/api/`.
- [x] New component or service code uses the adapter boundary in
`src/app/core/adapters/` instead of direct browser globals or imperative
third-party APIs.
- [x] User-facing strings use translation keys.
- [x] I added or updated tests appropriate to this change, or explained why
tests were not needed.
- [x] UI workflow changes include suitable e2e coverage, including
real-backend testing where relevant.
- [x] Commits are signed — see [Commit
Signing](CONTRIBUTING.md#commit-signing) in CONTRIBUTING.md.
- [x] I followed the [AI-assisted contributions
guidance](CONTRIBUTING.md#ai-assisted-contributions).
--
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.
To unsubscribe, e-mail: [email protected]
For queries about this service, please contact Infrastructure at:
[email protected]