У сучасних веб-додатках часто використовується автоматичне доповнення тексту, щоб полегшити користувачам введення інформації. Однак, іноді виникають проблеми з цим функціоналом, особливо коли мова йде про вимушений вибір елементів із списку. У цій статті розглянемо одну з таких проблем і спробуємо знайти рішення.
Зазначена проблема полягає в тому, що після введення тексту користувачем, а не вибору елемента зі списку автодоповнення, дані не зберігаються після натискання кнопки збереження. Це призводить до виникнення винятку в конвертері, де вказується, що “текст, введений користувачем”, не може бути знайдений, і інші поля зберігаються.
Для вирішення цієї проблеми необхідно внести зміни в автодоповнення або конвертер. Давайте розглянемо кожен із цих підходів.
Перш за все, слід звернутися до частини коду, де налаштовується компонент автодоповнення. У ньому вказано, що вимагається вибір елемента зі списку (forceSelection=”false”). Це означає, що користувач може вводити будь-який текст, а не обов’язково обирати елемент зі списку.
1 2 3 4 5 6 7 8 9 |
xhtml <h:form id="main"> <div> <p:outputLabel for="rate" value="Rate" styleClass="font-semibold"/> <p:autoComplete id="rate" value="#{forexBean.rateType.rateId}" class="w-full" var="rate" itemLabel="#{rate.currency}" itemValue="#{rate}" completeMethod="#{forexBean.autoCompletedRate}" converter="#{rateConverter}" minQueryLength="3" forceSelection="false" emptyMessage="sorry, no suggestions" moreText="more items available" scrollHeight="250" queryDelay="1400"> <p:ajax event="itemSelect" listener="#{forexBean.selectAutoCompleteRate}" process="@this" update="main:firstNamePanel main:lastNamePanel"/> </p:autoComplete> </div> </h:form> |
Як бачимо, параметр forceSelection встановлений в значення “false”, тобто вибір елемента не є обов’язковим. Однак, незважаючи на це, введений користувачем текст не зберігається. Це може виникати з-за особливостей реалізації автодоповнення у вашому додатку.
Другий підхід полягає у внесенні змін у конвертер, який обробляє дані перед їх збереженням. Давайте розглянемо частину коду конвертера, де проводиться опрацювання даних перед їх збереженням.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 |
converter public class RateConverter { public Object getAsObject(FacesContext context, UIComponent component, String value) { if (value != null && value.trim().length() > 0) { ForexService service = context.getApplication().evaluateExpressionGet(context, "#{forexService}", ForexService.class); RateType rate = new RateType(); try { return rate = service.getRateByCustomerId(value); } catch (Exception e) { RateType manualEntry = new RateType(); manualEntry.setCurrency(value); return manualEntry; } } return new RateType(); } public String getAsString(FacesContext context, UIComponent component, Object object) { if (Object != null) { return ((RateType) object).getUniqueCustomerId(); } else { return null; } } } |
У даному коді ми можемо побачити, що конвертер викликається для перетворення значення перед збереженням. Його завдання – перетворити рядок в об’єкт RateType. Проте, при введенні користувачем тексту, цей конвертер може не правильно обробляти дані, що призводить до виникнення винятку.
Для вирішення цієї проблеми можна змінити логіку конвертера так, щоб він правильно обробляв текст, введений користувачем. Наприклад, можна додати перевірку, чи є введений текст відомим елементом спис