PrimeFaces wizard component <p:wizard> is awesome, but recently in my work I was asked to get the tabs clickable, which are not by default in version 3.5.
This is a full tutorial explaining how you can achieve this.

To extend the wizard component to this feature, you can extend the WizardRenderer, and override encodeStepStatus method.

Here’s my ExWizardRenderer.java

package project.view.renderers;

import java.io.IOException;

import javax.faces.component.UIComponent;
import javax.faces.context.FacesContext;
import javax.faces.context.ResponseWriter;

import org.primefaces.component.tabview.Tab;
import org.primefaces.component.wizard.Wizard;

public class ExWizardRenderer extends org.primefaces.component.wizard.WizardRenderer {
	
	@Override
	protected void encodeStepStatus(FacesContext context, Wizard wizard) throws IOException {
		ResponseWriter writer = context.getResponseWriter();
        String currentStep = wizard.getStep();
        boolean currentFound = false;

        writer.startElement("ul", null);
        writer.writeAttribute("class", Wizard.STEP_STATUS_CLASS, null);
        int i = 0;
        for(UIComponent child : wizard.getChildren()) {
            if(child instanceof Tab && child.isRendered()) {
                Tab tab = (Tab) child;
                boolean active = (!currentFound) && (currentStep == null || tab.getId().equals(currentStep));
                String titleStyleClass = active ? Wizard.ACTIVE_STEP_CLASS : Wizard.STEP_CLASS;
                if(tab.getTitleStyleClass() != null) {
                    titleStyleClass = titleStyleClass + " " + tab.getTitleStyleClass();
                }
                
                if(active) {
                    currentFound = true;
                }

                writer.startElement("li", null);
                writer.writeAttribute("class", titleStyleClass, null);
                if(tab.getTitleStyle() != null) writer.writeAttribute("style", tab.getTitleStyle(), null);
                
                writer.startElement("a", null);
                final String wiz = wizard.resolveWidgetVar();
                writer.writeAttribute("href", "javascript:"+wiz+".loadStep("+wiz+".cfg.steps["+i+"], false)", null);
                if (tab.getTitletip() != null) writer.writeAttribute("title", tab.getTitletip(), null);
                writer.write(tab.getTitle());
                writer.endElement("a");
                
                writer.endElement("li");
                i++;
            }
        }

        writer.endElement("ul");
	}
	
} 

All am doing is adding a link around the title:

writer.startElement("a", null);

...

writer.endElement("a");

And then allowing this link to call the wizard javascript api function loadStep:

writer.writeAttribute("href", "javascript:"+wiz+".loadStep("+wiz+".cfg.steps["+i+"], false)", null);

Passing the second parameter of loadStep() as false, means don’t load the requested step if validation fails, change it to what suits you best.

To get this Renderer working, and allow it to take over the PrimeFaces WizardRenderer, add the next <renderer> to your faces-config.xml

<render-kit>
    <renderer>
        <component-family>org.primefaces.component</component-family>
        <renderer-type>org.primefaces.component.WizardRenderer</renderer-type>
        <renderer-class>project.view.renderers.ExWizardRenderer</renderer-class>
    </renderer>
</render-kit>

This is great so far, but I was asked for one more thing.  My wizard should be clickable in update scenario, and non clickable in create scenario, so users will be restricted to next and back buttons.

In my managed bean, I created a boolean property called updateScenario, clearly it will be true when am in edit mode. Add the next javascript to your .xhtml page containing the <p:wizard>

<script>
$(document).ready(function() {
    if (#{!myBean.updateScenario}) {
        $('li.ui-wizard-step-title a').prop('href', 'javascript:void(0)');
    }
});
</script>

All is good now, everything is as it’s supposed to be.

This tutorial was tested using JSF v2.1.0-b03, and PrimeFaces v3.5