RSoliveira
RSoliveira

Reputation: 31

Primefaces ajax update different panels according to backbean result

I'm new to JSF, Primefaces and Ajax, so what i'm trying to do is update one panel if a validation on my back bean is true and update another panel when it's false.

<h:panelGroup id="panel1">
    ...
    <h:commandButton id="btn1" action="#{bean.validate}">
        <p:ajax process="panel1" update="panel1"/>
    </h:commandButton>
</h:panelGroup>

<h:panelGroup id="panel2">
    ...
</h:panelGroup>

Back Bean:

public void validate() {
    ...
    if(validatecondition) {
        // Update panel 1
    } else {
        // update panel 2
    }
}

So is it possible to do this using ajax? Thanks in advance!!

Upvotes: 3

Views: 23663

Answers (3)

kolossus
kolossus

Reputation: 20691

Sure, two ways. Since you're using primefaces, the easier of two options would be

  1. Use the RequestContext object to update the panels selectively. Your code will look like this:

     public void validate() {
       RequestContext context = RequestContext.getCurrentInstance();
       if(validatecondition) {
         context.update("panel1");
       } else {
         context.update("panel2");
       }
    }
    
  2. JSF PartialViewContext can do the same job, with just a little more typing

    FacesContext ctxt = FacesContext.getCurrentInstance(); //get your hands on the current request context
         if(validatecondition) {
             ctxt.getPartialViewContext().getRenderIds().add("panel1");
           } else {
             ctxt.getPartialViewContext().getRenderIds().add("panel2");
           }
    

The getRenderIds() call returns a list of component Ids that JSF will update via ajax on completion of the response. This is basically what RequestContext in primefaces will do under the hood.

Upvotes: 8

Tony Shih
Tony Shih

Reputation: 436

JSF page code will be following in the backing bean the contents in a input will check and enable the correct panel accordingly. enter 1 in the input will activate panel 1, enter 2 for panel 2 and leave blank for both panels.

JSF is an excellent specification for enterprise application development it provides greater flexibility and separation of concern. Where you need to leave the user interface elements away from your business logic components. My solution is adheres to that principal by not referencing to UI element ids in the backing bean.

<?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:h="http://java.sun.com/jsf/html"
      xmlns:f="http://java.sun.com/jsf/core">
    <h:head>
        <title>Facelet Title</title>
    </h:head>
    <h:body>
        Hello from Facelets
        <h:form id="frm" >

            <h:commandButton value="click me" action="#{test2.aa()}">                
                <f:ajax execute="@form" render=":mainpanel" ></f:ajax> 
            </h:commandButton>
            <h:inputText id="intest" value="#{test2.selection}"></h:inputText> 

        </h:form>
        <h:panelGroup id="mainpanel">
            <h:panelGroup id="panel1" rendered="#{test2.prop1=='v'}">panel1
                <h:outputLabel id="lbl1" value="#{test2.prop1}" ></h:outputLabel>                
            </h:panelGroup>
            <h:panelGroup id="panel2" rendered="#{test2.prop2=='v'}">panel2
                <h:outputLabel id="lbl2" value="#{test2.prop2}"></h:outputLabel>
            </h:panelGroup>
        </h:panelGroup>
    </h:body>
</html> 

Backing bean code simple as possible I have used session scope also possible in request scope.

package test;

import javax.inject.Named;
import javax.enterprise.context.SessionScoped;
import java.io.Serializable;

@Named(value = "test2")
@SessionScoped
public class test2 implements Serializable {


    String prop1;
    String prop2;
    String selection;

    public String getProp1() {
        return prop1;
    }

    public void setProp1(String prop1) {
        this.prop1 = prop1;
    }

    public String getProp2() {
        return prop2;
    }

    public void setProp2(String prop2) {
        this.prop2 = prop2;
    }

    public test2() {
        prop1 = "v";
        prop2 = "v";
        selection = "";
    }

    public String getSelection() {
        return selection;
    }

    public void setSelection(String selection) {
        this.selection = selection;
    }

    public String aa() {
        if ("".equals(selection)) {
            prop1 = "v";
            prop2 = "v";
            return "";
        } else if ("1".equals(selection)) {
            prop1 = "v";
            prop2 = "h";
            return "";
        } else if ("2".equals(selection)) {
            prop1 = "h";
            prop2 = "v";
            return "";
        }
        return "";
    }
}

Upvotes: 0

partlov
partlov

Reputation: 14277

This is possible, and it is also easy if you are using PrimeFaces. But first I suggest you to make your button little more "primefaces like". Reorganize it to something like this:

<p:commandButton id="btn1" action="#{bean.validate}" process="panel1"/>

PrimeFaces button is AJAX enabled by default, so there is no need for additional tags. Remove update attribute (as we will do that in backing bean).

Now, your method in backing bean:

public void validate() {
  // ...
  if(validatecondition) {
    RequestContext.getCurrentInstance().update("panel1");
  } else {
    RequestContext.getCurrentInstance().update("panel2");
  }
}

RequestContext is one very useful class which you can use to update, reset fields or to execute some JavaScript after AJAX requests. In this example it is used just to conditionally update panel1 or panel2.

Upvotes: 4

Related Questions