1
votes

I have command buttons in the form. Those that are rendered on page load are invoking actions, but those two in the <p:fragment> tag are rendered on postback and are not working.

<h:form>
    <p:commandButton action="#{bean.actionA()}"/>
    <p:commandButton actionListener="#{bean.actionB()}"/>

    <p:fragment rendered="#{not empty bean.field}">
        <p:commandButton action="#{bean.actionA()}"/>
        <p:commandButton actionListener="#{bean.actionB()}"/>
    </p:fragment>

    <ui:include ..>
        ...
        <p:commandLink update="@form">
            <i class="fa fa-folder"></i>
            <f:setPropertyActionListener value="#{data.document}" target="#{bean.field}" />
        </p:commandLink>
    </ui:include>
</h:form>

I am noob in JSF. I know that issue is related to the JSF life cycle but I can not find a working solution.

My bean is view scoped and I use primefaces 5.1.

Is this suppose to work or I am ussing wrong approach to show/hide buttons?

Thanks.

EDIT:

After some testing it seams that even when action is invoked is invoked on bean with null==bean.field. This doesn't make sense to me, because I get rendered value #{bean.field.name} after update is done and hidden butons are displayed.

What am I missing?

Same effect when changing update=@form to update=@all.

Any help is appreciated.

My bean with session scope loks likek this. In this case of SessionScoped buttons are working. Why view scope is not enough?

import javax.annotation.PostConstruct;
import javax.faces.bean.ManagedBean;
import javax.faces.bean.SessionScoped;
import javax.faces.event.ActionEvent;
import javax.faces.view.ViewScoped;

import org.apache.log4j.LogManager;
import org.apache.log4j.Logger;

//TODO: change to @ViewScoped
@ManagedBean(name="bean")
@SessionScoped
public class Bean extends BeanBase {

private static final long serialVersionUID = 1L;
    private static final Logger LOGGER = LogManager.getLogger(Bean.class.getName());

    @PostConstruct
    protected void init() {
        super.init();
    }

    public void actionA() {
        LOGGER.debug("Action A triggerd!");
    }
    public void actionB( ActionEvent event) {
        LOGGER.debug("Action B event triggerd!");
        super.edit(event);
    }
}

View in browser. At bottom is icon that triggers in the middle rendered arrea. Buttons in that arrea are not active.

1
@stg Still the same issue. When I replace p:fragment with p:outputPanel or f:subview buttons do not trigger.urkon
As written here it should work on ´update=@form´. Thats exactly what I am doing. Im my case update of the form is called from the composite component. But it works as hidden buttons are displayed. But button actions are not properly set.urkon
@stg how can I test that and which expression. How to find it? Bean is in view scope. It works on action from working buttons,urkon
@stg I have updated the code with the bean.field setter and update call. I tried with the logging, but I do not know how to separate them into the JSF phases. On page load I have 12 cals of ´bean.field´ getter 3 of them are null. On button click I have 3 null returning getter cals. The difference is only that in one case action on bean is triggered. Hope this helps.urkon
It seams that even when action is invoked is invoked on bean with null==bean.field. What am I missing?urkon

1 Answers

1
votes

First of all, the p:fragment tag is supposed to use to partially submit and process fragments of your form during an AJAX call without the need to explicitly defining this behaviour on the corresponding components directly. Better just use e.g a p:outputPanel, if you just want a caontional rendering of a group of components.

But what is causing the problem here, is that the rendered attribut is not only evaluated when the form has to be rendered, but also when the form is processed. If, for some reason, the expression in the rendered attribut is now evaluated to false then processing the form will be stopped and the action will not be invoked. Just for security reasons.

In your case field is evaluated to null when the form is preocessed, thus the rendered attribute of the parent of your commandButton is evaluated to false and thats why the action method is not invoked.

The reason for this is, that the Scope of your ManagedBean is to small for some reason and/or it is destroyed after the render-response phase, so that, when you are clicking the command button, your are using a completly new instance of your managed bean where the value for field has never been set.

Most likely, your ManagedBean is in request scope instead of view scope, as you expected. Check if you are using the correct annotation the put the Bean in the correct scope and that you are not mixing up JSF and CDI annotations.