2015-07-13 6 views
1

Наше приложение использует Mojarra 2.1.29-03, и у нас возникают проблемы с атрибутами в наших пользовательских тегах при их копировании на вложенные теги.Пользовательские атрибуты тегов попадают в детей

Например, учитывая следующее определение тега:

cc.taglib.xml

<?xml version="1.0" encoding="UTF-8" ?> 
<facelet-taglib version="2.0" xmlns="http://java.sun.com/xml/ns/javaee" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-facelettaglibrary_2_0.xsd"> 
    <namespace>http://temp.com/jsf/customcomponents</namespace> 
    <tag> 
     <tag-name>wrapper</tag-name> 
     <source>wrapper.xhtml</source> 
     <attribute> 
      <description>The style class for the component</description> 
      <name>styleClass</name> 
     </attribute> 
    </tag> 
</facelet-taglib> 

wrapper.xhtml

<?xml version="1.0" encoding="UTF-8" ?> 
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd"> 
<html xmlns="http://www.w3.org/1999/xhtml"> 
    <ui:component xmlns:ui="http://java.sun.com/jsf/facelets"> 
     <div style="border: 1px solid black; margin: 5px;"> 
      <p>styleClass: #{styleClass}</p> 
      <ui:insert /> 
     </div> 
    </ui:component> 
</html> 

И клиент страница:

<?xml version="1.0" encoding="UTF-8"?> 
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd"> 
<html xmlns="http://www.w3.org/1999/xhtml" xmlns:h="http://java.sun.com/jsf/html" xmlns:cc="http://temp.com/jsf/customcomponents"> 
    <h:body> 
     <cc:wrapper styleClass="cc-style"> 
      <cc:wrapper /> 
     </cc:wrapper> 
    </h:body> 
</html> 

В результате минимумы:

styleClass: cc-style 

styleClass: cc-style 

... поэтому атрибут styleClass также применяется к внутреннему тегу даже если страница клиента не устанавливает его.

Мы отметили, что мы можем обойти это, обработав все клиентские страницы, чтобы установить styleClass = "", если он явно не установлен, но это подход, который мы бы хотели избежать (это очень уродливое решение и не может быть принудительно применено идти вперед).

Это ошибка? Есть ли способ обойти его, кроме упомянутого выше, желательно с обходным путем в теге, а не на клиентских страницах?

Благодаря Ivor

ответ

2

Это не совсем ошибка, но это действительно неинтуитивными и нежелательная поведение, которое должно было рассматриваться в JSF/Facelets спецификации.

Решение, основанное на работе, не является тривиальным, для устранения области действия Facelet необходим специальный манипулятор. Утилита JSF OmniFaces имеет версию 2.1 точно такой: <o:tagAttribute> (source code here).

Использование (не отметить, что пролог, DOCTYPE и HTML-теги не нужны, это файл в полном объеме):

<ui:composition 
    xmlns="http://www.w3.org/1999/xhtml" 
    xmlns:ui="http://java.sun.com/jsf/facelets" 
    xmlns:o="http://omnifaces.org/ui" 
> 
    <o:tagAttribute name="styleClass" /> 

    <div style="border: 1px solid black; margin: 5px;"> 
     <p>styleClass: #{styleClass}</p> 
     <ui:insert /> 
    </div> 
</ui:composition> 

Unrelated к конкретной проблеме, это не принято компонент, но файл tag. И в JSF 2.x термин «cc» обычно ассоциируется с составными компонентами, что совсем другое. Чтобы правильно использовать свои знания и терминологию (чтобы вы не путали себя или других при чтении своего кода), перейдите к When to use <ui:include>, tag files, composite components and/or custom components?

+0

Большое спасибо BalusC - мы застряли на Mojarra 2.1.x, и этот обработчик недоступен в 1.11 (как вы сказали), но использование источника, с которым вы связались, устранило нашу проблему. BTW: Я знаком с составными компонентами - должен был понять, что cc будет путать. Большое вам спасибо за ваш очень быстрый и полезный ответ. – haggisandchips

+0

Отлично. Пожалуйста :) – BalusC

0

Для информации мы идентифицировали альтернативный подход, который может быть полезен другим, так как он немного легче реализовать и понять.

Прежде всего, мне нужно добавить немного контекста к ситуации, в которой мы оказались ... мы недавно перешли от 2.1.12 до 2.1.29-03, и в рамках этого процесса мы изменили одно из наших зданий блоки из составного компонента (который имеет выделенную область для своих атрибутов) к пользовательскому тегу (который имеет описанное выше поведение). Такое же поведение в отношении атрибутов пользовательских тегов существовало в 2.1.12, но мы не знали об этом, поэтому вместо этого мы рассмотрели следующий подход: он восстановил бы поведение, которое у нас было до миграции, потому что нам нужно было бы применить его только к компоненту, который мы изменили.

wrapper.xhtml (я изменил пространство имен «кар», а не «см»)

<ui:component xmlns:ct="http://temp.com/jsf/customtags" xmlns:ui="http://java.sun.com/jsf/facelets"> 
    <ct:tagAttribute name="styleClass" /> 
    <div style="border: 1px solid black; margin: 5px;"> 
     <p>styleClass: #{styleClass}</p> 
     <ct:eraseAttribute name="styleClass" /> 
     <ui:insert /> 
    </div> 
</ui:component> 

Где tagAttribute это решение, предложенное BalusC, чтобы предотвратить тег, наследующий атрибуты своих родителей и в Кроме того, мы вызываем eraseAttribute-тег перед вызовом ui: insert, чтобы удалить атрибут из области (это, очевидно, требует, чтобы пользовательский тег был закончен с атрибутом). Это означает, что этот тег не наследует и не теряет атрибуты, а другие теги могут оставаться неизменными и поддерживать то же поведение, какое они имели до миграции.

ct.taglib.xhtml (фрагмент)

<tag> 
    <tag-name>eraseAttribute</tag-name> 
    <handler-class>com.temp.jsf.customtags.EraseTagAttribute</handler-class> 
    <attribute> 
     <name>name</name> 
     <required>true</required> 
     <type>java.lang.String</type> 
    </attribute> 
</tag> 

EraseTagAttribute.java

package com.temp.jsf.customtags; 

import java.io.IOException; 

import javax.faces.component.UIComponent; 
import javax.faces.view.facelets.FaceletContext; 
import javax.faces.view.facelets.TagConfig; 
import javax.faces.view.facelets.TagHandler; 

public class EraseTagAttribute extends TagHandler { 

    private final String name; 

    public EraseTagAttribute(TagConfig config) { 

     super(config); 

     name = getRequiredAttribute("name").getValue(); 
    } 

    public void apply(FaceletContext context, UIComponent parent) throws IOException { 

     context.getVariableMapper().setVariable(name, null); 
    } 
} 

В конце концов, мы не использовали его, однако, как мы чувствовали ответ предоставленный BalusC (который мы применили к каждому атрибут во всех наших пользовательских тегах) был правильным и понятным подходом, хотя он мог иметь дополнительные последствия в нашей конкретной ситуации.

 Смежные вопросы

  • Нет связанных вопросов^_^