0

I am having trouble to update the view from the bean in the back using PrimeFaces's RequestContext. In the example below I have a button and 2 panels. When pressing the button, I want to update one panel, but not the other one. It does not work though and I can't find the error! requestContext.update("panela"); is fired, but doesn't do its job! Help greatly appreciated!

The XHTML file:

<!DOCTYPE html>
<html xmlns="http://www.w3c.org/1999/xhtml"
      xmlns:h="http://java.sun.com/jsf/html"
      xmlns:p="http://primefaces.org/ui"
      xmlns:f="http://xmlns.jcp.org/jsf/core">
    <h:head/>
    <h:body>
        <h:form>
            <p:panelGrid columns="1">
                <p:commandButton value="Save" actionListener="#{runtimeUpdatesBean.save}" />
                <p:panel id="panela">
                    <h:outputText value="#{runtimeUpdatesBean.texta}"/>
                </p:panel>
                <p:panel id="panelb">
                    <h:outputText value="#{runtimeUpdatesBean.textb}"/>
                </p:panel>
            </p:panelGrid>
        </h:form>
    </h:body>
</html>

The bean:

package com.glasses.primework;

import javax.faces.bean.ManagedBean;
import javax.faces.bean.SessionScoped;
import org.primefaces.context.RequestContext;

@ManagedBean
@SessionScoped
public class RuntimeUpdatesBean {
    private String texta;
    private String textb;
    private boolean outcome;

    public String getTexta() {
        texta += "a";
        System.out.println("RuntimeUpdatesBean.getTexta() = " + texta);
        return texta;
    }

    public String getTextb() {
        textb += "b";
        System.out.println("RuntimeUpdatesBean.getTextb() = " + textb);
        return textb;
    }

    public void save() {
        RequestContext requestContext = RequestContext.getCurrentInstance();

        if(outcome) {
            System.out.println("RuntimeUpdatesBean.save() = update panela");
            requestContext.update("panela");
            outcome = false;
        } else {
            System.out.println("RuntimeUpdatesBean.save() = update panelb");
            requestContext.update("panelb");
            outcome = true;
        }
    }
}
Tiny
  • 27,221
  • 105
  • 339
  • 599
Socrates
  • 8,724
  • 25
  • 66
  • 113

2 Answers2

4

Well the problem is the ID of the component that you are referring.
In JSF when you place a component inside h:form (or Some Primefaces components like TabView), that component's Id will be generated based on the h:form id too.
Here is the Example:

<h:form id="panelaForm">
   <p:panel id="panela">
       ....
   </p:panel>
</h:form>

In the above case your p:panel's id will be generated as panelaForm:panela.
In your case since you haven't provided any ID for h:form a dynamic id will be attached like for example j_xyz:panela(you can see it using you browser's Inspect Element).

So If you wan to access p:panel with Id panela inside the same h:form then no need to attach the form Id.
But If you want to access the p:panel outside h:form then you need to attach the h:form id to access it.

Solution to you problem is: use an custom ID to your h:form (which is a best practice by the way..) and access the p:panel by attaching that form ID.

<h:form id="panelaForm">
   <p:panel id="panela">
       ....
   </p:panel>
</h:form>

And in Managed bean use:

RequestContext.getCurrentInstance().update("panelaForm:panela");
Luiggi Mendoza
  • 85,076
  • 16
  • 154
  • 332
Kishor Prakash
  • 8,011
  • 12
  • 61
  • 92
  • 1
    You can also set the prependId attribute from to false. Thereby the id from your form will not be prepended to the child elements. – Mahttias Schrebiér Dec 02 '14 at 08:49
  • 1
    @MahttiasSchrebiér: Yes you could but, that depends on how it affects the broader context of your application. If you are working in a very huge application and each page contain multiple `ui:include`s and each page included is developed by multiple developers across the globe than you cant guarantee that any two of them use same Id for their components. If Form ids are attached atleaset you could discriminate them based on module wise. – Kishor Prakash Dec 02 '14 at 09:08
  • 1
    You are right. I just wanted to refer to another possibility to handle that problem. In the most cases your way surely is the preferable solution in respect of modularity and programming with multiple developers. – Mahttias Schrebiér Dec 02 '14 at 09:27
0

I'm the new guy here (Java EE) however below solution works for me:

<!DOCTYPE html>
<html   xmlns="http://www.w3c.org/1999/xhtml"
    xmlns:h="http://java.sun.com/jsf/html"
    xmlns:p="http://primefaces.org/ui"
    xmlns:f="http://xmlns.jcp.org/jsf/core">
<h:head/>
<h:body>
    <h:form id="form">
        <p:panelGrid columns="1">
            <p:commandButton value="Save" actionListener="#{runtimeUpdatesBean.save}" update=":form" />
            <p:panel id="panela">
                <h:outputText value="#{runtimeUpdatesBean.texta}"/>
            </p:panel>
            <p:panel id="panelb">
                <h:outputText value="#{runtimeUpdatesBean.textb}"/>
            </p:panel>
        </p:panelGrid>
    </h:form>
</h:body>

Silwest
  • 1,620
  • 1
  • 15
  • 29
  • Hi @Silwestpl ! Thank you for your answer! But I must say that your code does not work. If you update the form, then automatically you will update both `panela` and `panelb`. Though the intention of this code is to decide within the `public void save() { ... }` which panel to update. – Socrates Nov 30 '14 at 17:11