Primefaces p:confirmDialog inside tabView

心不动则不痛 提交于 2019-12-06 12:37:21

It seems to work ok for me. See example below

<?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:f="http://java.sun.com/jsf/core"
    xmlns:h="http://java.sun.com/jsf/html"
    xmlns:ui="http://java.sun.com/jsf/facelets"
    xmlns:p="http://primefaces.org/ui">
<h:head>
    <title>JSF User Dialog</title>
</h:head>
<h:body>
    <h3>This is a JSF view.</h3>
    <h:form id="form">
        <p:confirmDialog global="true" showEffect="fade" hideEffect="explode">
            <h:form>
                <p:commandButton value="Yes" type="button"
                    styleClass="ui-confirmdialog-yes" icon="ui-icon-check" />
                <p:commandButton value="No" type="button"
                    styleClass="ui-confirmdialog-no" icon="ui-icon-close" />
            </h:form>
        </p:confirmDialog>

        <p:tabView id="tabView">

            <p:tab id="tab1" title="Tab one ">
                <p:commandButton value="Import" icon="ui-icon-arrowrefresh-1-w"
                    update=":form">
                    <p:confirm header="Confirmation" message="Are you sure?" />
                </p:commandButton>
            </p:tab>

            <p:tab id="tab2" title="Tab two">
                <p:commandButton value="Import" icon="ui-icon-arrowrefresh-1-w"
                    update=":form">
                    <p:confirm header="Confirmation" message="Are you sure?" />
                </p:commandButton>
            </p:tab>


        </p:tabView>
    </h:form>
</h:body>
</html>

Output:

It would be good if you post your full xhtml code so we can see what could be the problem there.

p:confirm does not implement state saving, thus it loses its attributes' values after the first JSF lifecycle. It also evaluates EL only once at view build time.

How to fix state saving.

You can extends PrimeFaces' ConfirmBehavior, implement saveState, restoreState, and override the original behavior in faces-config.xml by behavior-id org.primefaces.behavior.ConfirmBehavior. Then you'll be able to render and re-render p:confirm on subsequent requests.

How to fix state saving and reevaluate EL bound attribute values.

You should create your own my:confirm, because you need a custom taghandler, and you can't substitute a taghandler of another taglibrary's tag in a non-ugly way.

Create ConfirmBehavior.

package my;

import javax.faces.FacesException;
import javax.faces.component.UIComponent;
import javax.faces.component.behavior.ClientBehaviorContext;
import javax.faces.context.FacesContext;

import org.primefaces.behavior.base.AbstractBehavior;
import org.primefaces.component.api.Confirmable;
import org.primefaces.json.JSONObject;

public class ConfirmBehavior extends AbstractBehavior {

    public final static String BEHAVIOR_ID = "my.ConfirmBehavior";

    @Override
    public String getScript(ClientBehaviorContext behaviorContext) {
        FacesContext context = behaviorContext.getFacesContext();
        UIComponent component = behaviorContext.getComponent();
        String source = component.getClientId(context);
        String headerText = JSONObject.quote(this.getHeader());
        String messageText = JSONObject.quote(this.getMessage());

        if (component instanceof Confirmable) {
            String script = "PrimeFaces.confirm({source:\"" + source + "\",header:" + headerText + ",message:"
                    + messageText + ",icon:\"" + getIcon() + "\"});return false;";
            ((Confirmable) component).setConfirmationScript(script);

            return null;
        } else {
            throw new FacesException("Component " + source + " is not a Confirmable. ConfirmBehavior can only be "
                    + "attached to components that implement org.primefaces.component.api.Confirmable interface");
        }
    }

    public String getHeader() {
        return eval(PropertyKeys.header, null);
    }

    public void setHeader(String header) {
        setLiteral(PropertyKeys.header, header);
    }

    public String getMessage() {
        return eval(PropertyKeys.message, null);
    }

    public void setMessage(String message) {
        setLiteral(PropertyKeys.message, message);
    }

    public String getIcon() {
        return eval(PropertyKeys.icon, null);
    }

    public void setIcon(String icon) {
        setLiteral(PropertyKeys.icon, icon);
    }

    public enum PropertyKeys {
        header(String.class), message(String.class), icon(String.class);

        final Class<?> expectedType;

        PropertyKeys(Class<?> expectedType) {
            this.expectedType = expectedType;
        }
    }

    @Override
    protected Enum<?>[] getAllProperties() {
        return PropertyKeys.values();
    }

}

Create ConfirmBehaviorHandler.

package my;

import javax.faces.application.Application;
import javax.faces.view.facelets.BehaviorConfig;
import javax.faces.view.facelets.FaceletContext;
import javax.faces.view.facelets.TagAttribute;

import org.primefaces.behavior.base.AbstractBehaviorHandler;

public class ConfirmBehaviorHandler extends AbstractBehaviorHandler<ConfirmBehavior> {

    private final TagAttribute header;
    private final TagAttribute message;
    private final TagAttribute icon;

    public ConfirmBehaviorHandler(BehaviorConfig config) {
        super(config);
        this.header = this.getAttribute(ConfirmBehavior.PropertyKeys.header.name());
        this.message = this.getAttribute(ConfirmBehavior.PropertyKeys.message.name());
        this.icon = this.getAttribute(ConfirmBehavior.PropertyKeys.icon.name());
    }

    @Override
    protected ConfirmBehavior createBehavior(FaceletContext ctx, String eventName) {
        Application application = ctx.getFacesContext().getApplication();
        ConfirmBehavior behavior = (ConfirmBehavior) application.createBehavior(ConfirmBehavior.BEHAVIOR_ID);

        setBehaviorAttribute(ctx, behavior, this.header, ConfirmBehavior.PropertyKeys.header.expectedType);
        setBehaviorAttribute(ctx, behavior, this.message, ConfirmBehavior.PropertyKeys.message.expectedType);
        setBehaviorAttribute(ctx, behavior, this.icon, ConfirmBehavior.PropertyKeys.icon.expectedType);

        return behavior;
    }

}

Register ConfirmBehavior in faces-config.xml.

<?xml version="1.0" encoding="utf-8"?>
<faces-config xmlns="http://xmlns.jcp.org/xml/ns/javaee" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    xsi:schemaLocation="http://xmlns.jcp.org/xml/ns/javaee http://xmlns.jcp.org/xml/ns/javaee/web-facesconfig_2_2.xsd"
    version="2.2">

    <behavior>
        <behavior-id>my.ConfirmBehavior</behavior-id>
        <behavior-class>my.ConfirmBehavior</behavior-class>
    </behavior>

</faces-config>

Register ConfirmBehaviorHandler in your taglibrary my.taglib.xml.

<?xml version="1.0" encoding="UTF-8"?>
<facelet-taglib xmlns="http://xmlns.jcp.org/xml/ns/javaee" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    xsi:schemaLocation="http://xmlns.jcp.org/xml/ns/javaee http://xmlns.jcp.org/xml/ns/javaee/web-facelettaglibrary_2_2.xsd"
    version="2.2">

    <namespace>http://mycompany.ru/my</namespace>

    <tag>
        <tag-name>confirm</tag-name>
        <behavior>
            <behavior-id>my.ConfirmBehavior</behavior-id>
            <handler-class>my.ConfirmBehaviorHandler</handler-class>
        </behavior>
    </tag>

</facelet-taglib>

Now you can use my:confirm, just as you would use p:confirm, but with state saving and dynamic EL evaluation.

I had the same problem with the component. The proposed solution of removing the dynamic true works, but when we have to work in a dialog does not meet because the data are no longer updated automatically resulting in that the fields are blank. If this happens you must perform the following action. Ex:.

       <p:commandButton  style="font-size: 12px;width:30px;height:20px;"  icon="ui-icon-trash">
            <p:confirm header="Confirmação" message="Você realmente quer excluir o item de despacho?" icon="ui-icon-alert" />
       </p:commandButton>
       <p:growl id="growl" showDetail="true" />
       <p:confirmDialog global="true" showEffect="fade" hideEffect="explode" style="font-size: 12px;" closeOnEscape="true" widgetVar="confir">
            <p:commandButton id="confirm" value="Sim" ajax="true"  type="button" styleClass="ui-confirmdialog-yes" icon="ui-icon-check"  style="font-size: 12px;">
                <p:ajax event="click" listener="#{tableExpedicao.excluiItem}" update="confirm" oncomplete="confir.hide()"> </p:ajax>
            </p:commandButton>
            <p:commandButton value="Não" type="button" styleClass="ui-confirmdialog-no" icon="ui-icon-close" style="font-size: 12px;" oncomplete="confir.hide()"/>
     </p:confirmDialog>
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!