JSF 2: оболочка тега для инкапсуляции общих значений атрибутов?

На основе этого предыдущего вопроса Как получить идентификатор вызывающий компонент в методе получения?, вот еще одна идея, о которой я хочу спросить ваше мнение:

на страницах jsf много дублированного кода, такого как эти примеры (обратите внимание на повторяющийся атрибут size и maxlength) для компонентов:

<h:inputText label="#{msgs.userId}" id="UserId" value="#{userBean.userId}" 
   required="true" 
   size="#{variableConfigBean.getSize(component.id)}" 
   maxlength="#{variableConfigBean.getMaxLength(component.id)}"
/>
<h:inputSecret label="#{msgs.password}" id="Password" value="#{userBean.password}" 
   required="true"  
   size="#{variableConfigBean.getSize(component.id)}" 
   maxlength="#{variableConfigBean.getMaxLength(component.id)}"
/>

Я думал о :

  1. используя составной компонент для этого входного текстового тега,
  2. жестко запрограммировать размер и максимальную длину в разделе реализации этого составного компонента,
  3. так что мне не нужно дублировать все эти вещи каждый раз, когда мне нужно использовать этот компонент.
  4. но мне придется открыть все атрибуты в разделе интерфейса этого составного компонента

Подходит ли эта идея, или, возможно, есть другие лучшие способы решить эту проблему?


person Albert Gan    schedule 20.12.2010    source источник


Ответы (1)


Вы могли бы сделать это. Я также реализовал это в некоторых проектах. Это только добавляет некоторые (незначительные) накладные расходы. Для этой конкретной цели вы также можете просто использовать файл тега Facelets вместо составного компонента JSF. Тогда не обязательно определять атрибуты. В вашем конкретном случае вы можете реорганизовать в значительной степени дубликаты, если вы повторно используете имя свойства bean-компонента в качестве идентификатора и ключа для метки пакета сообщений.

E.g.

<my:input type="text" bean="#{userBean}" property="userId" required="true" />
<my:input type="secret" bean="#{userBean}" property="password" required="true" />

со следующим в файле тега Facelets:

<c:set var="id" value="#{not empty id ? id : property}" />
<c:set var="required" value="#{not empty required and required}" />

<c:choose>
    <c:when test="#{type == 'text'}">
        <h:inputText id="#{id}" 
            label="#{msgs[property]}"
            value="#{bean[property]}" 
            size="#{config.size(id)}" 
            maxlength="#{config.maxlength(id)}" 
            required="#{required}" />
    </c:when>
    <c:when test="#{type == 'secret'}">
        <h:inputSecret id="#{id}" 
            label="#{msgs[property]}"
            value="#{bean[property]}" 
            size="#{config.size(id)}" 
            maxlength="#{config.maxlength(id)}" 
            required="#{required}" />
    </c:when>
    <c:otherwise>
        <h:outputText value="Unknown input type: #{type}" />
    </c:otherwise>            
</c:choose>

Однако я реализовал его с <h:outputLabel> до и <h:message> после, что делает подобный рефакторинг более разумным.

person BalusC    schedule 20.12.2010
comment
Однако я реализовал его с помощью ‹h:outputLabel› до и ‹h:message› после, что делает такой рефакторинг более разумным. ‹-- Мне жаль, что я не понимаю это сообщение, не могли бы вы пояснить, мне любопытно :) .. Большое спасибо за решение, я сначала обновлю решение для пользовательского тега Facelet, прежде чем пробовать его. Но если я правильно помню, я не смогу прикрепить прослушиватели, валидаторы и т. д. для пользовательских тегов. Было ли это когда-нибудь проблемой для вас? И я впервые использую jstl на своей странице jsf, хе-хе-хе.. Спасибо! - person Albert Gan; 21.12.2010
comment
<h:outputLabel for="#{id}" value="#{msgs[property]}"/> перед <c:choose> и <h:message for="#{id}"/> после него. Что касается слушателей/валидаторов, я не уверен, но похоже, что вам просто нужно <ui:insert/> в теле тега. Между прочим, я не препятствую использованию композитного компонента. По моему опыту, в моем конкретном случае у них был тот недостаток, что они заканчивались как один компонент. Мое намерение состояло в том, чтобы иметь <h:panelGrid> из трех столбцов со всеми полями, и он работал только с файлом тегов, поскольку фактически возвращал 3 компонента (метка, ввод, сообщение) вместо одного. - person BalusC; 21.12.2010
comment
О, я вижу, вы думали о составном компоненте, возвращающем 3 компонента. хорошо :) Хорошо, я пробую ваши предложения сейчас. пожелай мне удачи. Спасибо еще раз.. - person Albert Gan; 21.12.2010