单击CommandLink后,Primefaces对话框字段未填充

时间:2014-04-10 14:37:21

标签: primefaces dialog

我正在使用Primefaces 3.5和Weblogic 11.我有一个页面,其中有一个对话框,用于编辑'个人资料'从两个地方调用的实体(' perfil' in Portuguese)。首先从commandButton插入新的配置文件。第二个是从dataTable编辑特定的配置文件。下面,我展示代码:

XHTML页面的片段

<p:fieldset legend="Pesquisa de Perfil">
    <p:panelGrid columns="2">
        <f:facet name="footer">
            <p:commandButton id="btnPesquisar"
                actionListener="#{perfilAcessoMB.pesquisar}" value="Pesquisar"
                immediate="true" update="pnlPerfis" styleClass="ui-icon-search" />
            <p:spacer width="20"></p:spacer>
            <!-- OPEN DIALOG TO CREATE A NEW PROFILE -->
            <p:commandButton id="btnIncluir" value="Incluir"
                update="dlgPerfil" immediate="true"
                actionListener="#{perfilAcessoMB.abrirDialogoEdicao(null)}"
                oncomplete="dlgPerfil.show();">
            </p:commandButton>
        </f:facet>
    </p:panelGrid>
</p:fieldset>

<br />

<p:outputPanel id="pnlPerfis" layout="block">
    <p:fieldset id="resultadoPesquisa" legend="Resultado da Pesquisa"
        rendered="#{not empty perfilAcessoMB.perfis}">
        <p:dataTable id="tblPerfis" value="#{perfilAcessoMB.perfis}"
            var="perfil" emptyMessage="Nenhum perfil encontrado.">
            <p:column headerText="Nome do Perfil">
                <h:outputText value="#{perfil.nome}"></h:outputText>
            </p:column>
            <p:column headerText="Descrição do Perfil">
                <h:outputText value="#{perfil.descricao}"></h:outputText>
            </p:column>
            <p:column headerText="Situação do Perfil"
                style="text-align: center; width: 100px;">
                <h:outputText value="Ativo" rendered="#{perfil.situacao}" />
                <h:outputText value="Inativo" rendered="#{not perfil.situacao}" />
            </p:column>
            <p:column headerText="Editar"
                style="text-align: center; width: 50px;">
                <!-- OPEN DIALOG TO EDIT A NEW PROFILE -->
                <p:commandLink id="lnkEditar" immediate="true"
                    title="Editar Perfil" update=":formPrincipal:dlgPerfil :formPrincipal:pnlPerfilEdicao"
                    actionListener="#{perfilAcessoMB.abrirDialogoEdicao(perfil)}"
                    oncomplete="dlgPerfil.show();">
                    <h:outputText value="Editar" />
                </p:commandLink>
            </p:column>
            <p:column headerText="Excluir"
                style="text-align: center; width: 50px;">
            </p:column>
        </p:dataTable>
    </p:fieldset>

</p:outputPanel>

<p:dialog id="dlgPerfil" widgetVar="dlgPerfil" resizable="false"
    closable="true" modal="true" closeOnEscape="true"
    header="#{(empty perfilAcessoMB.perfil)? 'Incluir': 'Editar'} Perfil">
    <h:outputText value="#{perfilAcessoMB.perfil}"></h:outputText>
    <h:panelGroup id="pnlPerfilEdicao" layout="block">
        <p:fieldset legend="Dados do Perfil">
            <p:panelGrid columns="2">
                <h:outputLabel id="lblNomePerfilEdicao" value="Nome do Perfil"
                    for="txtNomePerfilEdicao" />
                <p:inputText id="txtNomePerfilEdicao" required="true"
                    requiredMessage="É obrigatório preencher o campo Nome do Perfil."
                    value="#{perfilAcessoMB.perfil.nome}" maxlength="20" size="20"></p:inputText>

                <h:outputLabel id="lblDescricaoPerfilEdicao"
                    value="Descrição do Perfil" for="txtDescricaoPerfilEdicao" />
                <p:inputText id="txtDescricaoPerfilEdicao" required="true"
                    requiredMessage="É obrigatório preencher o campo Descrição do Perfil."
                    value="#{perfilAcessoMB.perfil.descricao}" maxlength="20"
                    size="20"></p:inputText>

                <h:outputLabel id="lblSituacaoPerfilEdicao" value="Situação"
                    for="selSituacaoPerfilEdicao" />
                <p:selectOneMenu id="selSituacaoPerfilEdicao"
                    value="#{perfilAcessoMB.perfil.situacao}">
                    <f:selectItems value="#{perfilAcessoMB.situacoesEdicao}" />
                </p:selectOneMenu>
            </p:panelGrid>
        </p:fieldset>
        <br />
        <p:fieldset legend="Permissões">
            <p:pickList id="pickFuncoes" value="#{perfilAcessoMB.funcoes}"
                var="funcao" itemValue="#{funcao}"
                itemLabel="#{funcao.descricao}" required="true"
                requiredMessage="É obrigatório associar ao menos uma funcionalidade ao perfil."
                converter="funcaoConverter" />
            <p:column>#{funcao.descricao}</p:column>
        </p:fieldset>
        <p:panelGrid columns="2">
            <p:commandButton id="btnSalvarPerfil" value="Salvar"
                actionListener="#{perfilAcessoMB.salvar}"
                oncomplete="if(args &amp;&amp; !args.validationFailed) dlgPerfil.hide();" />
            <p:commandButton id="btnCancelarPerfil" value="Cancelar"
                immediate="true" onclick="dlgPerfil.hide();" />
        </p:panelGrid>
    </h:panelGroup>
</p:dialog>

MangedBean(perfilAcessoMB)

@ManagedBean
@ViewScoped
public class PerfilAcessoMB extends BaseMB {

    private PerfilAcessoORM perfil;

    private List<PerfilAcessoORM> perfis;

    private String nomePerfil;

    private Boolean situacao;

    private DualListModel<FuncaoORM> funcoes;

    private SelectItem[] situacoesPesquisa = new SelectItem[] {
            new SelectItem(null, "Todos"), SELECT_ITEM_ATIVO,
            SELECT_ITEM_INATIVO };

    private SelectItem[] situacoesEdicao = new SelectItem[] {
            SELECT_ITEM_ATIVO, SELECT_ITEM_INATIVO };

    private FuncaoORM funcaoA = new FuncaoORM(1L, "FUNÇÃO A"), //
            funcaoB = new FuncaoORM(2L, "B Function"), //
            funcaoC = new FuncaoORM(10L, "Se Funssaum");

    public void abrirDialogoEdicao(PerfilAcessoORM p) {
        this.perfil = (p == null)? new PerfilAcessoORM(): p;
        System.out.println("PerfilAcessoMB.onAbrirDialogoEdicao(): "
                + this.perfil);

        List<FuncaoORM> funcoesDisponiveis = new ArrayList<FuncaoORM>(
                Arrays.asList(funcaoA, funcaoB, funcaoC));
        // Remove from funcoesDisponiveis those whose are present in perfil.
        if (this.perfil.getFuncoes() == null) {
            this.funcoes = new DualListModel<FuncaoORM>(funcoesDisponiveis,
                    Lists.<FuncaoORM> newArrayList());
        } else {
            funcoesDisponiveis.removeAll(this.perfil.getFuncoes());
            this.funcoes = new DualListModel<FuncaoORM>(funcoesDisponiveis,
                    this.perfil.getFuncoes());
        }
    }

    // Getters & Setters

}

PerfilAcessoORM(个人资料)实体

public class PerfilAcessoORM  {

    private Long id;

    private String nome;

    private String descricao;

    private Boolean situacao = null;

    private List<FuncaoORM> funcoes;

    // Getters & Setters

}

FuncaoORM实体:

public class FuncaoORM {

    private Long id;

    public String descricao;

    // Getters & Setters

}

我的问题是什么?显然,当我想插入一个新的配置文件时,一切似乎都可以。但是,当我点击编辑现有的个人资料以打开对话框时,虽然正确填充了outputTextpickList,但inputText&{39}和selectOneMenu是不。

在寻找解决方案时,我发现here建议在对话框中使用appendToBody="true"。当我尝试时,inputText&{39}和selectOneMenu已正确填充。但是,验证不能等待。当我点击保存时,会显示一条消息,表明pickList未填充,即使它已被填充。实际上,即使inputText未填写,也没有关于这些inputText的消息,尽管它们是必需的。

另一种替代方法是在<f:setPropertyActionListener>内使用commandLink

<!-- OPEN DIALOG TO CREATE A NEW PROFILE -->
<p:commandButton id="btnIncluir" value="Incluir"
    update="dlgPerfil" immediate="true"
    actionListener="#{perfilAcessoMB.abrirDialogoEdicao}"
    oncomplete="dlgPerfil.show();">
    <f:setPropertyActionListener target="#{perfilAcessoMB.perfil}" value="#{null}"/>
</p:commandButton>


<!-- OPEN DIALOG TO EDIT A NEW PROFILE -->
<p:commandLink id="lnkEditar" immediate="true"
    title="Editar Perfil" update=":formPrincipal:dlgPerfil :formPrincipal:pnlPerfilEdicao"
    actionListener="#{perfilAcessoMB.abrirDialogoEdicao}"
    oncomplete="dlgPerfil.show();">
    <f:setPropertyActionListener target="#{perfilAcessoMB.perfil}" value="#{perfil}"/>
    <h:outputText value="Editar" />
</p:commandLink>

actionListener方法将更改为:

public void abrirDialogoEdicao() {
    if(this.perfil == null) {
        this.perfil = new PerfilAcessoORM();
    }
    System.out.println("PerfilAcessoMB.onAbrirDialogoEdicao(): "
            + this.perfil);
    // The rest remains the same ...
}

现在,当我点击创建一个新的perfil时,虽然在actionListener方法中填充了perfil属性,但在重新定义对话框时我得到了NullPointerException。它就像第一个叫做perfilAcessoMB.setPerfil(),在对话框打开后最后是actionListener方法。另一方面,如果我点击编辑现有的个人资料,我会回到初始状态。

因此,我迷失了,不知道如何解决这个问题。

谢谢,

Rafael Afonso

1 个答案:

答案 0 :(得分:1)

解决方案非常简单:只需将process="@this"添加到commandButtons。

<!-- OPEN DIALOG TO EDIT A NEW PROFILE -->
<p:commandLink id="lnkEditar" immediate="true"
    title="#{msg['titulo.edicao']}" process="@this"
    update=":formPrincipal:dlgPerfil"
    actionListener="#{perfilAcessoMB.abrirDialogoEdicao(perfil)}"
    oncomplete="dlgPerfil.show();">
    <h:outputText value="#{msg['titulo.edicao']}" />
</p:commandLink>