2010-06-21 4 views
4

Рассмотрим простой составной компонент, который принимает параметр действия какого-либо рода - например, «prettifier» простой ссылки. Я хочу «ajaxify» его.JSF 2.0 Компонентные компоненты - параметр ajax render. Определение компонента OUTSIDE

<composite:interface> 
     <composite:attribute name="act" method-signature="java.lang.String action()"></composite:attribute> 
     <composite:attribute name="text" required="true"></composite:attribute> 
      <composite:clientBehavior name="click" event="action" targets="l"/> </composite:interface> 

    <composite:implementation> 
     <h:commandLink id="l" act="#{cc.attrs.action}" immediate="true">   <b>#{cc.attrs.text}</b>   </h:commandLink> </composite:implementation> 

я выставить событие через поведение клиента. Я использую это так:

<h:panelGroup layout="block" id="outside"> 

     #{mybean.otherdata} <br/> 

       <mc:mylink text="Click click" action="#{mybean.click}" > 
        <f:ajax event="click" render="outside"/>" 
       </mc:mylink><br/> 

</h:panelGroup> 

Вы можете увидеть, что я хочу сделать: Я хочу сделать Ajax визуализации вне композит определения; просто настройка рендеринга на «внешний» дает ошибку <f:ajax> contains an unknown id.

Да, я знаю об именах контейнеров, и я знаю, что мы можем добавить двоеточие и указать абсолютный путь, но это довольно неуклюжий. Если я закрою его еще несколькими слоями (это весь смысл), мне придется связать эти ссылки вместе вручную.

Могу ли я сделать некоторую ссылку, например render="../outside", чтобы пропустить ссылку на родительский контейнер компонента?

Я сделал приложение jsf 1 с a4j, и этот шаблон использовался повсюду.

+0

автор: «Этот шаблон использовался повсюду» Я имею в виду, что a4j, похоже, поднимается вверх по контейнерной иерархии, пока не найдет матч. составной компонент def, кажется, завершает поиск на границе компонента – james

ответ

1

Вы можете использовать render="@all" или render="@form", чтобы сделать все, или целиком, соответственно.

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

+0

. @all не работает - по крайней мере, с mojarra. @form делает. – james

+1

@ работает, протестирован с JBoss AS 7.1.0.CR1b. но в большинстве случаев это слишком тяжело –

1

После некоторого лужения, вот одно решение:

Положите слушателя на событие:

<f:ajax event="click" listener="#{mycomp.listen}" render="#{mycomp.getParId('outside')}"/>" 

Реализация:

public void listen(AjaxBehaviorEvent event) { 
    String clid=event.getComponent().getClientId(); 

    StringTokenizer st=new StringTokenizer(clid,":"); 

    StringBuilder sb=new StringBuilder(":"); 
    for (int x=1;x<st.countTokens();x++) 
    { 
     sb.append(st.nextToken()).append(":"); 
    } 

    parId=sb.toString(); 
} 

public String getParId(String suff) { 
    //must precheck as id is prevalidated for existence. if not set yet set to form 
    if (parId==null) 
    { 
     return "@form"; 
    } 
    return parId+suff; 
} 

Даже так, почему вы должны это сделать?

1

Я нашел еще лучшее решение, которое я доволен тем, что использует неявное «компонентное» отображение в шаблоне. Он позволяет базовое относительное отображение обратно из составного компонента с использованием нотации файловой системы ../. Он может быть расширен, чтобы обрабатывать больше, но это все, что мне нужно. Он также работает для выполнения параметра.

Я хотел бы поблагодарить меня за выяснение этого! Опять же, я что-то не понимаю? Мне не нужно было это разбираться.

Использование:

<mc:mylink text="Click me" action="#{blah.myaction}" render="../../pg" /> 

Реализация:

<composite:implementation> 

    <h:commandLink id="l" action="#{cc.attrs.action}" immediate="true"> 
     <f:ajax render="#{pathProcessor.pathProcess(3, cc.attrs.render, component.clientId)}" /> 
        #{simon.rand} . <b>#{cc.attrs.text}</b> 
    </h:commandLink> 

..... 

метод pathprocessor:

public static String pathProcess(int currentNesting, String path, String clid) { 

    //System.out.println("clientid is "+clid); 
    //System.out.println("path is "+path); 
    //System.out.println("nesting is "+currentNesting); 

    String backTok="../"; 
    String sepchar=":"; 

    StringBuilder src=new StringBuilder(path); 
    int backs=0; 
    int inc=backTok.length(); 

    while (src.indexOf(backTok,backs*inc)==backs*inc) 
    { 
     backs++; 
    } 

    //get rid of the source 
    String suffix=src.substring(backs*inc); 

    //add in internal nesting 
    backs+=(currentNesting-4); 

    StringTokenizer st=new StringTokenizer(clid,sepchar); 

    StringBuilder sb=new StringBuilder(sepchar); 
    for (int x=0;x<st.countTokens()-backs;x++) 
    { 
     sb.append(st.nextToken()).append(sepchar); 
    } 

    //backtracked path 
    String p=sb.toString(); 

    //add suffix to the backtracked client path to get full absolute path 
    String abs=p+suffix; 

    return abs; 
} 

Errrr - Я не знаю, почему я использовал StringBuilder при подсчете спины, но вы получаете идею. Это что-то вроде этого.

7

В JSF 2.0 вы можете использовать неявные cc и component объектов внутри EL. Для того, чтобы принести полный идентификатор клиента для любого компонента сделать:

#{component.clientId} 

Чтобы получить идентификатор клиента для составного компонента сделать:

#{cc.clientId} 

Таким же образом, вы также можете принести родителю #{cc.parent} , В этом случае это, вероятно, то, что вы хотите. Для более длинного ответа см. Acquire full prefix for a component clientId inside naming containers with JSF 2.0.

0

cc.parent.cliendId разрешает родительский составной компонент вместо непосредственного родителя. Obtaining the clientId of the parent of a JSF2 composite component

<composite:interface> 
    <cc:attribute name="render" type="java.lang.String" default="@this"/> 
    <cc:attribute name="action" method-signature="java.lang.String action()"> 
</composite:interface> 

</composite:implementation> 
    <h:form> 
     <h:commandLink action="#{cc.attrs.action}" value="Click"> 
      <f:ajax render="{cc.attr.render}" execute="@form" 
     </h:commandLink> 
    </h:form>  
</composite:implementation> 

Таким образом, вы можете решить самостоятельно, какой компонент вы собираетесь оказывать.

<h:panelGroup layout="block" id="outside"> 
    #{mybean.otherdata} 
    <mc:mylink action="#{mybean.click}" render=":outside"/> 
</h:panelGroup>    
Смежные вопросы