2013-02-27 5 views
2

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

Я написал составной компонент, поддерживаемый автономным управляемым компонентом, ограниченным представлением.
Компонент состоит из текстового окна автозаполнения с кнопкой, которая открывает диалог. Пользователь может выбрать элемент по имени (автозаполнение) или выбрать узел в дереве (диалог).
Бэк-бэк реализует все необходимое (доступ к данным, древовидную логику и т. Д.) И должен выставлять выбранный элемент (как POJO).

Теперь у меня есть 2 проблемы:

  1. Из-за сложности управления дерева, selectedObj собственность, доступ по геттер и сеттер, которые делают некоторые вещи в бобе: они не просто доступ к класса. Теперь я передаю весь компонент в качестве атрибута. Как я могу сделать selectedObj bean-атрибутом «значение» моего составного компонента?

  2. Как я могу использовать несколько экземпляров моего компонента в одном представлении?

Ниже приведен пример компонента:

<cc:interface> 
    <cc:attribute name="bean" type="com.yankee.OUTreeBean" required="true"/> 
    <cc:attribute name="listener" method-signature="void listener()"/> 
</cc:interface> 
<cc:implementation> 
    <p:dialog id="#{cc.id}_dialog" widgetVar="_dlg" header="Select OU" modal="true" dynamic="true" > 
     <p:toolbar> 
      <!-- some buttons to refresh, expand, collapse etc. --> 
     </p:toolbar> 
     <p:tree id="#{cc.id}_tree" value="#{cc.attrs.bean.root}" var="node" 
       selectionMode="single" 
       selection="#{cc.attrs.bean.selectedNode}"> 
      <p:ajax event="select" update="@form" listener="#{cc.attrs.listener}" oncomplete="if (!args.validationFailed) _dlg.hide()" /> 
      <p:treeNode> 
       <h:outputText value="#{node.OU_NAME}" /> 
      </p:treeNode> 
     </p:tree> 
    </p:dialog> 

    <p:autoComplete id="#{cc.id}_inner" value="#{cc.attrs.bean.selectedObj}" completeMethod="#{cc.attrs.bean.completeObj}" 
        var="obj" itemLabel="#{obj.OU_NAME}" itemValue="#{obj}" 
        forceSelection="true" 
        converter="ouConverter" 
        multiple="false" 
        minQueryLength="2"> 
     <p:ajax event="itemSelect" listener="#{cc.attrs.listener}" update="@form"/> 
    </p:autoComplete> 
    <div style="float: right"> 
     <p:commandButton id="bSearch" icon="ui-icon-search" onclick="_dlg.show()"/> 
    </div> 
</cc:implementation> 

Подкладочный боба из КОМПОНЕНТА:

@ManagedBean 
@ViewScoped 
public class OUTreeBean implements Serializable { 
    private static final long serialVersionUID = 1L; 

    private List<OU> data; // Data as plain list 
    protected TreeNode root; // root node of data as a tree 
    protected TreeNode selectedNode; 

    @PostConstruct 
    private void init() throws SQLException { 
     refreshData(); 
    } 

    public OU getSelectedObj() { 
     if (selectedNode == null) { 
      return null; 
     } 
     return ((OU) selectedNode.getData()); 

    } 
    public void setSelectedObj(OU ou) { 
     // Find the right tree node and do whatever needed 
    } 
    public TreeNode selectedNode getSelectedNode() { 
     // Blah blah 
    } 
    public void setSelectedNode(TreeNode selectedNode) { 
     // Blah blah 
    } 
    public List<OU> completeObj(String namePattern) { 
     // Autocomplete handler 
    } 
    public void refreshData() { 
     // Blah blah 
    } 
    // etc... 

} 

используя страницу выдержка:

<ism:selectOUTree id="cbSelectOu" bean="#{myBean.ouFilterBean}" listener="#{myBean.onOUChange}"/> 

подкладочного bean of PAGE:

@ManagedBean 
@ViewScoped 
public class MyBean implements Serializable { 

    private static final long serialVersionUID = 1L; 
    @ManagedProperty("#{oUTreeBean}") 
    private OUTreeBean ouFilterBean; 

    public void onOUChange() throws SQLException { 
     // Blah blah 
    } 
} 
+0

он должен работать с '# {cc.attrs.value}' где 'value =" # {myBean.ouFilterBean.selectedObj} ", если у вас есть правильный правильный приемник и сеттер –

+0

@ Christophe Roussy Хорошо, спасибо, но цель состоит в том, чтобы «скрыть» компонент бланка компонента из компонента страницы. 'MyBean' не должен знать о существовании' OUTreeBean', поэтому компонент должен быть привязан к свойству MyBean типа 'OU' – yankee

+0

. Предоставьте некоторый getter и setter в myBean, который позволяет напрямую обращаться к объекту (принудительно выполнить это посредством реализации интерфейса ...) –

ответ

1

У меня была такая же проблема несколько дней назад. Как и вы, я использовал ManagedBean как объект, который должен выполнять эту работу. Через некоторое время я понял, что должен просто создать FacesComponent. Я новичок в JSF, так что найти решение было не так просто, но он решил все мои проблемы. Вот как это работает:

View.xhtml

<h:body> 
    <cc:interface componentType="playerComponent"> 
     <cc:attribute name="playerId" required="true"/> 
    </cc:interface> 
    <cc:implementation> 
     <c:set var="inplaceId" value="inplace-#{cc.attrs.playerId}" /> 
     <c:set var="outputId" value="output-#{cc.attrs.playerId}" /> 
     <h:form id="form-#{cc.attrs.playerId}"> 
      <p:inplace editor="false" widgetVar="#{inplaceId}"> 
       <h:inputText value="#{cc.player.name}" id="outputId"/> 
       <p:commandButton onclick="#{inplaceId}.save()" action="#{cc.save}" update="#{outputId}" value="save" /> 
       <p:commandButton onclick="#{inplaceId}.cancel()" update="#{outputId}" value="cancel" /> 
      </p:inplace> 
     </h:form> 
    </cc:implementation> 
</h:body> 

PlayerComponent.java

@FacesComponent("playerComponent") 
public class PlayerComponent extends UINamingContainer { 

    private Player player; 

    private void init() { 
     Object idObj = getAttributes().get("playerId"); 
     if (idObj != null) { 
      // create player object 
     } 
    } 

    public void save() { 
     // save player object 
    } 

    public Player getPlayer() { 
     if (player == null) { 
      init(); 
     } 
     return player 
    } 
} 

Player.java (юридическое лицо)

public class Player { 
    private name; 
    public String getName() { 
     return name; 
    } 

    public void setName(String name) { 
     this.name = name; 
    } 

} 

Как я уже писал, я новый в JSF и, возможно, объект игрока должен быть создан по-разному (используя @PostConstruct в конструкторе?), но это wo гк.

+0

Спасибо, пепуч. Я также попытался преобразовать свой @ManagedBean в @FacesComponent, но я не могу понять, как связать значение компонента с параметром, например. как вы «используете» свой ' yankee

+0

@yankee, ' pepuch

+0

Я только что обнаружил, что пользовательский компонент имеет область запроса и даже использует State Helper (см. Ответ BalusC на [этот вопрос] (http://stackoverflow.com/questions/13702370/how-to-prevent-multiple-composite-components -reset-yourself-on-a-jsf-page? rq = 1)), чтобы имитировать '@ ViewScope', слишком сложна для моего случая, потому что некоторые объекты будут воссозданы. Вместо этого подход [родительский/дочерний компонент] (http://stackoverflow.com/questions/3710075/whats-the-correct-way-to-create-multiple-instances-of-managed-beans-in-jsf-2 -0), кажется, отлично работает для проблемы 2). Тем не менее я не могу понять ваш подход к 1) – yankee

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