2015-12-08 2 views
1

Я использую omnifaces o:tree «ветвей», где каждая ветвь имеет «список листьев» с атрибутом «цвет», который должен быть доступен для редактирования в дереве.ui: repeat in o: дерево работает не так, как ожидалось

- branch 0 
    - leaf 0 (color = "green") 
    - leaf 1 (color = "yellow") 
- branch 1 
    - leaf 0 (color = "purple") 
    - branch 1_0 
    - leaf 1 (color = "red") 
    - leaf 2 (color = "orange") 
    - leaf 3 (color = "brown") 

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

Но изменение цвета или удаление листа (так что все, что находится в пределах ui:repeat) работает только на последнюю визуализированную ветвь.

«Цветные» поля ввода для других листов/ветвей вообще не работают, а ссылка удаления листьев в пределах ui:repeat также не работает, как для атрибута листа в removeLeaf (...) всегда получает соответствующий лист из последней обработанной ветви. Итак, в приведенном выше примере щелчок по удалению для желтого цвета лист из ветки 0 назовет removeLeaf (оранжевый, ветвь 0), который затем явно ничего не удалит, поскольку ветка 0 не имеет оранжевого листа.

Это код стянуть к основной части - все остальное может быть предоставлена ​​в случае необходимости:

<h:form> 
    <o:tree value="#{treeBean.tree}" var="branchEntity" varNode="branchNode"> 
    <o:treeNode> 
     <o:treeNodeItem> 
     <ui:repeat value="#{branchEntity.leafList}" var="leaf"> 
      <h:panelGrid columns="2">  
      <p:inputText value="#{leaf.color}" /> 
      <p:commandLink action="#{treeBean.removeLeaf(leaf, branchEntity)}" styleClass="ui-icon ui-icon-trash" 
         process="@form" update="@form" />    
      </h:panelGrid> 
     </ui:repeat>  

     <p:commandLink action="#{treeBean.addLeaf(branchEntity)}" styleClass="ui-icon ui-icon-plus" 
       process="@form" update="@form" /> 
     <o:treeInsertChildren /> 
     </o:treeNodeItem> 
    </o:treeNode> 
    </o:tree> 
    <p:commandButton id="save" value="Save" action="#{treeBean.save}" process="@form" update="@form" /> 
</h:form> 

Я знаю, что есть некоторые issue с вложенными ui:repeat, но, как я на Mojarra 2.1.19 Наверное, это не так. И фактическое гнездование двух ui:repeats прекрасно работает, если я заменю o:tree на ui:repeat, который перебирает список ветвей. Но тогда я, очевидно, потерял функциональность дерева, которая мне нужна. Это я только что проверил, чтобы проверить, правильно ли вложенные ui:repeat.

Эта проблема, кажется, похож на another question, но это не совсем то же самое ...

Если я заменить внутреннюю ui:repeat на p:dataList (как это было предложено в некоторых других ответах решить ui:repeat проблемы, а также теперь в ответе BalusC) ссылки removeLeaf() будут работать нормально, но будут привязаны только поля ввода цвета для последней ветви.

ОБНОВЛЕНИЕ: Теперь у меня был более близкий взгляд при использовании p:dataList. Содержание POST из запроса AJAX, который я получил от моих инструментов браузеров разработчиков выглядит хорошо:

javax.faces.partial.ajax=true 
javax.faces.source=hForm:save 
javax.faces.partial.execute=hForm 
javax.faces.partial.render=hForm 
hForm:save=hForm:save 
hForm=hForm 
hForm:oTree:0:pDataList:0:color=green 
hForm:oTree:0:pDataList:1:color=yellow 
hForm:oTree:1:pDataList:0:color=purple 
hForm:oTree:1_0:pDataList:0:color=red 
hForm:oTree:1_0:pDataList:1:color=orange 
hForm:oTree:1_0:pDataList:2:color=brown 
javax.faces.ViewState=-6137230173999059936:-6718691551411872927 

метод treeBean.save() только вход всего Tree.toString() на консоль, которая заканчивается так: !

[Branch [leafList=[Leaf [color=null], Leaf [color=null]]], 
Branch [leafList=[Leaf [color=null]]] 
[Branch [leafList=[Leaf [color=red], Leaf [color=orange], Leaf [color=brown]]]]] 

Если цвет имел некоторое значение = NULL прежде, значение остается неизменным - так он не получает перекрываться нуль. Я еще недостаточно глубоко в JSF, чтобы действительно знать, как исследовать, где информация теряется на этом пути.

(Первоначально я использовал Mojarra 2.1.19 на JBoss EAP 6.2 + Primefaces 5.2 + Omnifaces 2.1, но также точно так же на Mojarra 2.2.12, TomEE, Primefaces 5.3 + Omnifaces 2.2.Полный проект Maven Eclipse можно найти here Я добавил еще один простой атрибут String (без списка) непосредственно в филиал, который отлично работает.)

ответ

1

Это действительно вызвано ошибкой управления состоянием в <ui:repeat>. Он неправильно распознал себя, будучи вложенным в другой итератор, и упрямо очищает состояние до того, как его пересматривают во время каждой итерации родительского итератора. Он only признает родителя UIRepeat или UIData, но все. <o:tree> не распространяется и не может простираться от UIData, а UIRepeat, к сожалению, является классом, специфичным для реализации, и поэтому его нельзя использовать публично до тех пор, пока вы хотите быть независимым от конкретной реализации JSF (Mojarra, MyFaces и т. Д.).).

Ваш лучший выбор - заменить <ui:repeat> реальным компонентом UIData, который имеет намного лучшую реализацию государственного управления. Я просто попробовал его здесь, и добавление предметов отлично подходит для меня с <h:dataTable> и <p:dataList>. Только удаление элементов не удавалось с <h:dataTable>, поскольку оно отображало неверные идентификаторы клиентов. Он не учитывает идентификатор клиента контейнера. <p:dataList> работал для меня в обоих случаях добавления и удаления элементов. Все еще обновление модели на стороне сервера любых связанных полей ввода в списке не выполняется, как подробно описано в комментариях к этому ответу.

Замены всей <ui:repeat> на более <p:dataList type="none"> (без type, он воздаст <ul><li>) является ближайшим вы можете получить.

<p:dataList type="none" value="#{branchEntity.leafList}" var="leaf"> 
    ... 
</p:dataList> 

Мир был бы намного проще, если бы JSF предложил открытый интерфейс UIRepeat -как (маркер), который все эти повторители могли бы просто проверить, когда они собираются управлять государством.

+0

Итак, вы подали jsf 2.4 улучшение? ;-) Или можете или вы, или Арьен, проскользнуть в 2.3 под видом? ;-) – Kukeltje

+0

Это определенно в нашем списке пожеланий 2.3. – BalusC

+0

Thx для быстрого ответа. Но на самом деле это не работает для меня. С 'h: dataTable' вещи начинают становиться действительно сумасшедшими для меня. Например, ссылка removeLeaf получает имя n-раз и удаляет ВСЕ (1-го) листа из любых ветвей. Если я просматриваю сгенерированный html, идентификатор для ссылки deleteLeaf выглядит как 'hForm: oTree: hDataTable: 0: removeLeaf'. Тот же идентификатор, созданный при использовании 'p: dataList', выглядит как' hForm: oTree: 1_0: pDataList: 0: removeLeaf' и отлично работает. Но в этом случае inputText не работает. 'ui: repeat',' h: dataTable', 'p: dataList' ведут себя по-разному, но не так, как я хочу. – mineralf