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 специально для этой цели.

Ответы на вопрос(0)

Ваш ответ на вопрос