Primefaces p: inplace: Как более элегантно распространять выражение EL для объединения объектов
Я хотел бы поделиться следующим мощным "взломать" для получения объекта, значение которого было отредактировано с использованием p: inplace.
Мой вопрос о том, как добиться этого более элегантно, используя другие существующие атрибуты p: inplace или иным образом.
Уловка взята из предложения BalusC о Stackoverflow:
JSF (и PrimeFaces) Как передать параметр в метод в ManagedBean
Вопрос состоит в том, чтобы получить объект Employee, у которого есть отредактированный p: inplace # {emp.firstName}:
<h:outputText value="First name:"/>
<p:inplace id="firstname" editor="true">
<p:ajax event="save" onsuccess="#{employeeController.saveName()}"/>
<p:inputText id="firstName" value="#{emp.firstName}"
required="true" label="text"
valueChangeListener="#{employeeController.firstNameChanged}">
<p:ajax event="valueChange" listener="#{employeeController.onValueChangedStart}"/>
</p:inputText>
</p:inplace>
Предложение от BalusC:
Assuming that you're indeed inside a repeating component where #{emp} is been exposed by its var attribute, you could just grab it from the EL scope inside the value change listener as follows:
FacesContext context = FacesContext.getCurrentInstance();
Employee employee = context.getApplication().evaluateExpressionGet(context, "#{emp}", Employee.class);
Long id = employee.getId();
Проблема в том, что выражение EL (в данном случае # {emp}) жестко запрограммировано, поэтому его нельзя использовать повторно.
Теперь я успешно использую идентификатор p: inplace для распространения строки, которая может быть проанализирована как выражение EL для объекта в слушателе, однако, поскольку нельзя использовать точку ». в строке идентификатора я должен переводить каждый "." как хайфен '-' а затем преобразовать это в действительное выражение EL в слушателе. Таким образом, я могу распространять очень сложные выражения EL, а затем я знаю, какую сущность нужно объединить с базой данных (или какая требуется операция сохранения).
public static String policy_convert_id_to_el_expression(String $id) {
if ($id == null) {
throw new IllegalArgumentException("null String $id");
}
return $id.replaceAll("-", ".");
}
У меня есть семейство глубоких значений сущностей, которые обертывают определенные мелкие значения, такие как BooleanValue, FloatQuantity и т. Д., Каждый из которых имеет специально типизированный метод getValue () и универсальный переходный метод getObject () и содержит другие постоянные метаданные обернутого поверхностного значения (например, единицы, автор и т. Д.).
У меня есть компонент поддержки ValueManager с:
public void onInplaceSaveEvent(AjaxBehaviorEvent ae) {
UIComponent component = ae.getComponent();
String id = component.getId();
String $el = policy_convert_id_to_el_expression(id);
FacesContext context = FacesContext.getCurrentInstance();
Value v = context.getApplication().evaluateExpressionGet(context, "#{" + $el + "}", Value.class);
..
// merge Value entity to database (catches change to shallow wrapped value)
// and/or perform other persistence operations such as metadata updates
..
}
Теперь это стратегия многократного использования.
Например, у меня есть объект OfficeBuilding с List getFloors (), и у каждого BuildingFloor есть глубокая сущность FloAQuantity getArea (), где FloatQuantity расширяет Value.
В dataTable я перебираю переменную var = floor over value = # {officeBuilding.floors} и редактирую мелкое значение .value области следующим образом:
<p:inplace
id="floor-area"
editor="true"
emptyLabel="UNDEF"
>
<p:ajax
event="save"
update="@form"
listener="#{valueManager.onInplaceSaveEvent}"
process="@this floor-area-value"
/>
<p:inputText
id="floor-area-value"
value="#{floor.area.value}"
/>
</p:inplace>
Это может быть инкапсулировано как удобный для повторного использования и удобный составной компонент resources / util / inplaceValue.xhtml, таким образом:
<cc:interface>
<cc:attribute name="value" type="com.example.entity.value.Value" required="true"/>
<cc:attribute name="elid" required="true"/>
</cc:interface>
<cc:implementation>
<p:inplace
id="#{cc.attrs.elid}"
editor="true"
emptyLabel="UNDEF"
>
<p:ajax
event="save"
update="@form"
listener="#{valueManager.onInplaceSaveEvent}"
process="@this #{cc.attrs.elid}-value"
/>
<p:inputText
id="#{cc.attrs.elid}-value"
value="#{cc.attrs.value.value}"
/>
</p:inplace>
</cc:implementation>
Используя приведенный выше пример, это называется:
<util:inplaceValue elid="floor-area" value=#{floor.area}/>
Нужно просто помнить, чтобы быть осторожным при указании атрибута elid что все вхождения "." в выражении EL переводятся как hiphen "-", но это работает как обаяние для широкого спектра сложных случаев, и это экономит огромное количество кодирования. Это довольно элегантно, но это все же взломать.
Вопрос: Как можно лучше передать слушателю выражение EL, необходимое для доступа к объекту, значение которого было отредактировано?
У меня такжесделал предложение функции Primefaces для нового атрибута для p: inplace специально для этой цели.