Не удается отобразить элементы в другой форме из динамически загружаемой вкладки jQuery-tabs

у меня есть главная страница, так как она содержит составной компонент интересов и ссылки для вкладок с ленивой загрузкой следующим образом:

1 – страница профиля:

<?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">
<ui:composition template="../templates/application.xhtml"
    xmlns="http://www.w3.org/1999/xhtml"
    xmlns:h="http://java.sun.com/jsf/html"
    xmlns:ui="http://java.sun.com/jsf/facelets"
    xmlns:o="http://omnifaces.org/ui"
    xmlns:f="http://java.sun.com/jsf/core"
    xmlns:myapp="http://java.sun.com/jsf/composite/component"
    xmlns:p="http://java.sun.com/jsf/passthrough">
        <ui:define name="head">
    <title>Profile</title>
    <script type="text/javascript" src="https://www.google.com/jsapi"></script>
    <link rel="stylesheet" type="text/css" href="#{request.contextPath}/resources/assets/css/jquery/jquery-ui.css" media="screen"/>
    <link rel="stylesheet" type="text/css" href="#{request.contextPath}/resources/assets/css/override-jquery.css" media="screen"/>
    <style>
        li
        {
            outline: none !important;
        }​
    </style>
    </ui:define>

<ui:define name="right-side">
    <div class="three-column right">          
    <myapp:interest bean="#{interestBean}" value="#{interestBean.interest}" id="interestCmp"></myapp:interest>              
    </div>
</ui:define>    
<ui:define name="content">
    <div class="tabs">
        <ul>
            <li><a id="tab1" href="tabs/tab1.xhtml">tab1</a></li>
            <li><a id="tab2" href="tabs/tab2.xhtml">tab2</a></li>
        </ul>
    </div>


<script type="text/javascript">head.ready(function(){$('.tabs').tabs();});</script>
</ui:define>
</ui:composition>

Композитный компонент 2 – интересы:

<?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:f="http://java.sun.com/jsf/core"
    xmlns:ui="http://java.sun.com/jsf/facelets" xmlns:composite="http://java.sun.com/jsf/composite">

<composite:interface>
    <composite:attribute name="id" />
    <composite:attribute name="index" />
    <composite:attribute name="value" />
    <composite:attribute name="bean" /> 
</composite:interface>

<composite:implementation xmlns:myapp="http://java.sun.com/jsf/composite/component">
<div >
<aside class="interests">
    <header class="header-w-flag icon-star">
        <h1>Interests</h1>
    </header>
    <h:form id="interestForm">
    <h:panelGroup id="showInterests" layout="block">
    <ui:repeat var="interest" value="#{interestBean.getUserInterests()}" >
        <div class="interest">
        <div class="interest-name"><a href="">#{interest.interestName}</a> 
        <h:commandLink  action="#{interestBean.deleteInterest(interest)}" rendered="#{permissionBean.isCurrentUser(profileBean.user)}" >
        <i class="icon-delete control-icon" style="cursor:pointer;display:none;"></i>
        <f:ajax render="@form" execute="@this"></f:ajax>
        </h:commandLink></div>
        <div class="people-grid"> 
        <ui:repeat var="user" value="#{interestBean.getUsersByInterest(interest.id)}" varStatus="status" >
        <h:panelGroup id="interestedUsers">
                            <a title="#{user.firstName} #{user.lastName}" href="../profile/index.xhtml?id=#{user.id}"><img src="#{applicationBean.avatarBaseURL}#{user.avatarUrl}" alt="#{user.firstName}" /></a>
        </h:panelGroup>
        </ui:repeat>
        </div>


       </div>
    </ui:repeat>
    </h:panelGroup>
   </h:form>
</aside>

        </div>
</composite:implementation>
</html>

3- код вкладки 1:

<?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:ui="http://java.sun.com/jsf/facelets"
    xmlns:o="http://omnifaces.org/ui"
    xmlns:f="http://java.sun.com/jsf/core"
    xmlns:myapp="http://java.sun.com/jsf/composite/component"
    xmlns:p="http://java.sun.com/jsf/passthrough">

   <div id="tab1">
            <!-- feed here -->
            <h:panelGroup layout="block" class="posts" id="feedContainer">
            <h:form id="profileFeeds">
            <ui:repeat var="post" value="#{feedBean.feeds}" varStatus="status" >
                <myapp:feedpost value="#{post}" index="{status.index}"></myapp:feedpost>    
            </ui:repeat>
            <h:panelGroup layout="block" rendered="#{feedBean.feeds.size()==0}">
                <div class="post blue">
                    <div class="post-content">

                        <h1>Nothing</h1>

                    </div>
                </div>
            </h:panelGroup>  

            <div class="post load"><h:commandLink action="#{feedBean.getMoreHomeFeeds()}" styleClass="btn btn-primary btn-small">Show more feeds
            <f:ajax render=":feedContainer" ></f:ajax>
            </h:commandLink></div>
            </h:form>
        </h:panelGroup>
    </div>



</html>

4 – составной компонент фидпоста, связанный с вкладкой 1:

<?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:f="http://java.sun.com/jsf/core"
    xmlns:ui="http://java.sun.com/jsf/facelets" xmlns:composite="http://java.sun.com/jsf/composite">

<composite:interface>
    <composite:attribute name="id" />
    <composite:attribute name="index" />
    <composite:attribute name="value" />

</composite:interface>

<composite:implementation xmlns:myapp="http://java.sun.com/jsf/composite/component">
    <h:panelGroup layout="block" class="post">
    <div class="post-content">      




                <h:panelGroup layout="block">
                        <h1><h:outputFormat value="#{cc.attrs.value.title}" /></h1>
                </h:panelGroup>

tText value="#{baseBean.replaceWithHTMLBreak(cc.attrs.value.note)}" escape="false"/></p>
                </h:panelGroup>


        </div>
    <myapp:comments value="#{cc.attrs.value}"></myapp:comments>
    </h:panelGroup> 
</composite:implementation>

</html>

5- составной компонент комментариев, связанный с компонентом фидпост:

<?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:f="http://java.sun.com/jsf/core"
    xmlns:ui="http://java.sun.com/jsf/facelets" xmlns:composite="http://java.sun.com/jsf/composite">

<composite:interface>
    <composite:attribute name="id" />
    <composite:attribute name="index" />
    <composite:attribute name="value" />    
</composite:interface>

<composite:implementation>
        <h:panelGroup layout="block" class="comments" id="feedcomments">
        <div class="actions">

            <h:commandLink id="addToInterestLink" value="#{msg['action.addto.interests']}" styleClass="action-like"
                action="#{feedBean.addToInterests(cc.attrs.value)}">
                <f:ajax  execute="@this" render=":interestCmp:interestForm:showInterests"></f:ajax>
            </h:commandLink>

        </div>
    </h:panelGroup>
</composite:implementation>

</html>

при нажатии на ссылку tab1 (вкладка jquery с ленивой загрузкой), которая содержит составной компонент комментариев, который имеет ссылку для отображения интереса div в компоненте интереса, я получаю следующее исключение:

<f:ajax> contains an unknown id ':interestCmp:interestForm:showInterests' - cannot locate it in the context of the component addToInterestLink

ПРИМЕЧАНИЕ. один обходной путь, который я нашел для решения этой проблемы, заключается в том, чтобы статически добавить содержимое tab1 на страницу, а не связывать его.

посоветуйте как это исправить.


person Mahmoud Saleh    schedule 20.11.2013    source источник
comment
Кажется, вы отредактировали код в своем вопросе в недопустимой форме. Использование : в идентификаторе компонента JSF вызовет только IAE. В будущих вопросах, пожалуйста, скопируйте настоящий код без изменений. В противном случае вы только вводите отвлекающие маневры и путаницу.   -  person BalusC    schedule 21.11.2013
comment
@BalusC, я разместил правильный код сейчас, извините, я неправильно понял код страницы, также извините за путаницу, я обещаю, что больше так не буду.   -  person Mahmoud Saleh    schedule 22.11.2013
comment
В этом коде есть 2 странные вещи: 1) <f:ajax render> не использует префикс :, хотя сообщение об ошибке упоминает об этом; вы все еще показываете реальный код? 2) Вы подразумеваете, что все работает нормально, когда вы заменяете <ui:repeat> чем-то более простым, например привет? И есть одна неясность: является ли <myapp:interest> составным компонентом с <cc:interface><cc:implementation> и т. д.? Вы именно продолжаете называть это композицией, а не композицией.   -  person BalusC    schedule 23.11.2013
comment
@BalusC, теперь я исправил рендеринг, код ошибки. ссылка с функцией рендеринга находится внутри вкладки на странице, когда я пытаюсь щелкнуть вкладку, я получаю исключение на консоли, поэтому рендеринг вообще не работает, потому что вкладка не загружена. составной компонент, извините за путаницу, я все еще учусь.   -  person Mahmoud Saleh    schedule 23.11.2013
comment
Что ж, мой первоначальный ответ остается в силе. Используйте render=":interestForm:showInterests". Разве это не сработало?   -  person BalusC    schedule 23.11.2013
comment
@MahmoudSaleh, как указал BalusC, все связанные идентификаторы должны начинаться с :   -  person kolossus    schedule 23.11.2013
comment
@BalusC, я добавил еще одно обновление, в котором указана причина этого исключения.   -  person Mahmoud Saleh    schedule 23.11.2013
comment
В будущем вопросы пост реального SSCCE. Когда вы публикуете код, вы должны всегда убедиться, что любой (включая вас самих!) сможет воспроизвести описанную проблему, просто скопировав предоставленный фрагмент кода без изменений прямо в <h:body> страницы без шаблона в среде. со всеми настройками по умолчанию (если не указано иное, например, параметры web.xml и т. д.).   -  person BalusC    schedule 23.11.2013
comment
@BalusC, я так и сделаю, извиняюсь за путаницу.   -  person Mahmoud Saleh    schedule 23.11.2013
comment
@BalusC, что посоветуете по этому поводу?   -  person Mahmoud Saleh    schedule 23.11.2013
comment
Сначала опубликуйте настоящий SSCCE.   -  person BalusC    schedule 24.11.2013
comment
@BalusC, теперь добавлен полный код.   -  person Mahmoud Saleh    schedule 25.11.2013
comment
Спасибо, но это абсолютно не SSCCE, поэтому для выяснения проблемы потребуется еще много времени.   -  person BalusC    schedule 26.11.2013
comment
На всякий случай SSCCE означает короткий, автономный, правильный (компилируемый), пример (sscce.org)... Как сказал BalusC, любой может легко воспроизвести проблему, а затем начать работать над ее решением.   -  person dgimenes    schedule 28.11.2013


Ответы (1)


Хорошо, в двух словах и несколько упрощенно (композитные компоненты на самом деле не играют роли в проблеме), ваша проблема здесь:

profile.xhtml:

<my:composite id="interestCmp"> <!-- Yes, invalid code; just to summarize. -->
    <h:form id="interestForm">
        <h:panelGroup id="showInterests">
            ...
        </h:panelGroup>
    </h:form>
</my:composite>
<div class="tabs">
    <ul>
        <li><a id="tab1" href="tabs/tab1.xhtml">tab1</a></li>
        <li><a id="tab2" href="tabs/tab2.xhtml">tab2</a></li>
    </ul>
</div>
<script>head.ready(function(){$('.tabs').tabs();});</script>

И где-то в tab1.xhtml

<h:form id="profileFeeds">
    <h:commandLink value="Add">
        <f:ajax render=":interestCmp:interestForm:showInterests" />
    </h:commandLink>
</h:form>

Таким образом, вы используете вкладки пользовательского интерфейса jQuery для создания панели с вкладками с динамическим содержимым. Однако вкладка tab1.xhtml не использует то же представление JSF, что и главная страница profile.xhtml. Это физически совершенно разные виды. Это полностью объясняет, почему <f:ajax> не смог найти нужный компонент в дереве компонентов (текущее представление). Он может видеть только те компоненты, которые содержатся в самом tab1.xhtml. Он не видит те из profile.xhtml. Он даже не может видеть тех, кто находится в tab2.xhtml.

Это будет работать только в том случае, если вы предварительно загрузите вкладки с помощью <ui:include> вместо их динамической загрузки. Таким образом, tab1.xhtml физически окажется в том же виде, что и желаемый компонент. Предположим, что вам нужно сделать это только для tab1.xhtml, а tab2.xhtml можно оставить динамически загруженным. Это должно решить вашу проблему:

<div class="tabs">
    <ul>
        <li><a id="tab1" href="#tab1_page">tab1</a></li>
        <li><a id="tab2" href="tabs/tab2.xhtml">tab2</a></li>
    </ul>
    <div id="tab1_page">
        <ui:include src="tabs/tab1.xhtml" />
    </div>
</div>

Вам нужно всего лишь заменить <?xml...?><!DOCTYPE ...><html xmlns...> и </html> из tab1.xhtml (а также tab2.xhtml) на <ui:composition xmlns...> и </ui:composition> соответственно. Потому что в противном случае вы получите синтаксически недопустимый HTML.

Если вам действительно нужны динамически/лениво загружаемые вкладки, вам лучше поискать полноценный компонент JSF, способный выполнить эту работу, например PrimeFaces <p:tabView>. Более того, PrimeFaces использует jQuery/UI под прикрытием для внешнего вида, так что многие вещи будут очень похожи на текущий подход.

person BalusC    schedule 28.11.2013