2

I have two tabs. With the wizard component, when i press the 'Next' button (FROM THE FIRST TAB), I need to populate a list(with SelectItem objects) and then show these SelectItems in a SelectOneMenu tag IN THE SECOND TAB. As i soon i have finished entering data on THE FIRST TAB and then press the 'Next' button, this SelectOneMenu tag(ON THE SECOND TAB) does not have anything in it.

Basically, i need to update the next tab along with the processing of the current tab. Anyway to do this?

Thanks in advance.

enter image description hereenter image description here

Here is my code:

<p:wizard widgetVar="wiz" showNavBar="true" flowListener="#{detentionForm.onFlowProcess}">
                <p:tab id="typeOfLeader" title="Leader Selection">
                    <p:panel header="Leader Selection">
                        <p:messages showSummary="true" showDetail="false"/>
                        <p:panelGrid columns="2">
                            #{msgs.typeOfLeaderPunishment}
                            <p:selectOneMenu value="#{detentionForm.typeOfLeaderSelectedID}" style="width:400px" panelStyle="width:150px" effect="fade">
                                <f:selectItems value="#{detentionForm.teacherTypes}" var="type" itemLabel="#{type.label}" itemValue="#{type.value}" />
                            </p:selectOneMenu>
                        </p:panelGrid> 
                    </p:panel>
                </p:tab>
                <p:tab id="typeOfPunishment" title="Punishment Type">
                    <p:panel header="Type of Punishment">
                        <p:panelGrid columns="2">
                            #{msgs.typeOfDetention}
                            <p:selectOneMenu value="#{detentionForm.typeOfPunishment}" style="width:400px" panelStyle="width:150px" effect="fade" >
                                <f:selectItems value="#{detentionForm.detentionTypes}" var="type" itemLabel="#{type.label}" itemValue="#{type.value}" />
                            </p:selectOneMenu> 
                        </p:panelGrid>

                    </p:panel>
                </p:tab>

            </p:wizard>

#{detentionForm.detentionTypes} is an arraylist that needs to be populated once i press the 'Next' button to the SECOND TAB.


Here is my backing bean:

@ViewScoped
@Named("detentionForm")
public class DetentionFormBean implements Serializable{
    @Resource(name="jdbc/DetentionCentre")
    private DataSource ds;

    private Details details = (Details) FacesContext.getCurrentInstance().getExternalContext().getSessionMap().get("userDetails");



    private String typeOfPunishment;
    private String typeOfLeader = details.getTypeOfLeader(); //Can change if user is House Leader. Eg. They can become a teacher when making a punishment
    private int typeOfLeaderID; //ID in the database of the teacher's type of leadership
    private int typeOfLeaderSelectedID = 1; //Set default to teacher as House leader can be teacher and normal teacher will be a teacher!
    private ArrayList<SelectItem> detentionTypes = new ArrayList<SelectItem>(); //SelectItem objects that shows what punishments each teacher can do
    private ArrayList<SelectItem> teacherTypes = new ArrayList<SelectItem>(); //SelectItem objects that shows what type of leadership a teacher can be (Teacher or House Leader)


    //gets all the data necessary from the database to show on the page
    @PostConstruct
    public void initialize(){
        this.setTypeOfLeaderID(details.getUserName()); //gets the ID from the database to find out the default type of leadership
        this.findTeacherTypes(this.typeOfLeader); 
    } 

    public String onFlowProcess(FlowEvent event) {  //change later for backing as well >>>>>>>>>>>>>>
            String stepToGo = event.getNewStep();
            if(stepToGo.equals("typeOfPunishment")){
                this.findDetentionTypes();

            }
        return stepToGo;

    }

    //populates teacherType Arraylist depending the user's teacher type. House Leader can be a Teacher or a House Leader.
    private void findTeacherTypes(String type) {
        if(type.equals("House Leadership Team")){
            this.teacherTypes.add(new SelectItem(Integer.toString(this.typeOfLeaderID), type)); //House leader is 2
            this.teacherTypes.add(new SelectItem(Integer.toString(this.typeOfLeaderID - 1), "Teacher" )); //Teacher is 1
        }else{ //type is Teacher
            this.teacherTypes.add(new SelectItem(Integer.toString(this.typeOfLeaderID), type)); //Teacher is 1
        }
    }


    //populates detentiontypes depending on type of leader
    private void findDetentionTypes() {
        System.out.println(">>>>Inside findDetentionTypes()!!!");
        PreparedStatement ps;
        Connection con;
        String sqlInitialData = "SELECT r.punishment_type, p.type FROM detentioncentredb.tbl_teacher_roles_allowed_punishments r, detentioncentredb.tbl_punishment_types p WHERE r.teacher_roles = ? AND p.ID = r.punishment_type";
        ResultSet rs;

        try {
            con = ds.getConnection();
            ps = con.prepareStatement(sqlInitialData);
            ps.setString(1, Integer.toString(this.typeOfLeaderSelectedID)); 
            rs = ps.executeQuery();
            while(rs.next()){
                SelectItem s = new SelectItem(rs.getString("punishment_type"), rs.getString("type"));
                this.detentionTypes.add(s);
            }
            rs.close();
            ps.close();
            con.close();

        } catch (SQLException ex) {
            Logger.getLogger(DetentionFormBean.class.getName()).log(Level.SEVERE, null, ex);
        }
    }

    //getter and setter methods

    public String getTypeOfPunishment() {
        return typeOfPunishment;
    }

    public void setTypeOfPunishment(String typeOfPunishment) {
        this.typeOfPunishment = typeOfPunishment;
    }

    public String getTypeOfLeader() {
        return typeOfLeader;
    }

    public ArrayList<SelectItem> getDetentionTypes() {
        return detentionTypes;
    }

    public ArrayList<SelectItem> getTeacherTypes() {
        return teacherTypes;
    }

    public int getTypeOfLeaderID() {
        return typeOfLeaderID;
    }

    //gets the typeOfLeader the current user is from the database. This retrieves the ID of the teacher's type of leadership. NOT WHAT THE TEACHER SELECTED.
    private void setTypeOfLeaderID(int userName){
        PreparedStatement ps;
        Connection con;
        String sqlTypeOfLeaderID = "SELECT TypeOfLeader FROM detentioncentredb.tbl_teachers WHERE RegNumber = ?";
        ResultSet rs;
        try {
            con = ds.getConnection();
            ps = con.prepareStatement(sqlTypeOfLeaderID);
            ps.setInt(1, userName);
            rs = ps.executeQuery();
            while(rs.next()){
                this.typeOfLeaderID = rs.getInt("TypeOfLeader");
            }
            rs.close();
            ps.close();
            con.close();
        } catch (SQLException ex) {
            Logger.getLogger(DetentionFormBean.class.getName()).log(Level.SEVERE, null, ex);
        }
    }

    public int getTypeOfLeaderSelectedID() {
        return typeOfLeaderSelectedID;
    }

    public void setTypeOfLeaderSelectedID(int typeOfLeaderSelectedID) {
        this.typeOfLeaderSelectedID = typeOfLeaderSelectedID;
    }


}
Apoorv Kansal
  • 3,210
  • 6
  • 27
  • 37
  • What is primeface's version ? I'm using v4.0RC1 and every changes made inside onFlowProcess() is updated. – Ghetolay Nov 07 '13 at 14:15

1 Answers1

2

You can use ajax to notify the server side you are stepping into your wizard. From PF documentation:

If you’d like get notified on server side when wizard attempts to go back or forward, define a flowListener.

<p:wizard flowListener="#{userWizard.handleFlow}">
...
</p:wizard>

public String handleFlow(FlowEvent event) {
    String currentStepId = event.getCurrentStep();
    String stepToGo = event.getNextStep();
    if(skip)
        return "confirm";
    else
        return event.getNextStep();
    }

In your case, you need to load detentionTypes array when stepToGo reaches typeOfPunishment, based on what user has selected on the first step of the wizard:

public String handleFlow(FlowEvent event) {
    String stepToGo = event.getNextStep();
    if(stepToGo.equals("typeOfPunishment")){
        detentionTypes = service.loadDetentionTypes(this.TypeOfLeaderSelectedID);
    }
}
Aritz
  • 30,971
  • 16
  • 136
  • 217
  • Yeah, I tried that. It populates the list, however it doesn't update the page, therefore leaving SelectOnempMenu with nothing in it. That is problem I am having. – Apoorv Kansal Apr 01 '13 at 11:29
  • Can you post your backing bean code? Specially what you're doing into the flow listener method. You should also debug that method and see what values are into the array. – Aritz Apr 01 '13 at 16:01
  • Added the back bean code to the question. I have done exactly what you said for that flow listener. I have debugged the application and I see that my `detentionTypes` arraylist is getting populated. However, the next tab isn't rendered again to use that populated arraylist. – Apoorv Kansal Apr 02 '13 at 00:16
  • 1
    I've noticed a problem there. I haven't used `p:wizard` tag, but JSF 2 `@ViewScoped` beans [are destroyed](http://stackoverflow.com/a/12798102/1199132) when you return something that's not `null` or empty String in your backing bean. So that probably is the problem you have with your `handleFlow` method, you return the next step of the wizard and the bean is being rebuilt, so you loose your values. As a solution, you could try to load your values when the `change` event of your first combo is fired and get rid of the `handleFlow` method. – Aritz Apr 02 '13 at 07:03
  • Thanks for your reply. But it is still not changing the next selectOneMenu tag in the next tab. I used an ajax tag inside the first selectOneMenu tag and chucked in a listener which loads the values. – Apoorv Kansal Apr 03 '13 at 01:02
  • Check that the getter method of `detentionTypes` is really returning such values. – Aritz Apr 03 '13 at 05:52
  • wait with ViewScoped, does that mean ALL my methods have to be void? What would happen with the getter methods? – Apoorv Kansal Apr 03 '13 at 07:15
  • Absolutelly no. It means that every ACTION method you want to execute has to remain with void or empty `String` if you want the bean to keep its state. You can check it in an easy way with a breakpoint in bean's constructor method. – Aritz Apr 03 '13 at 09:28