P: steps but allow click on all steps

I have steps using labels using the <p:steps> , as shown below:

 <p:steps activeIndex="3" styleClass="custom" readonly="false" style="padding: 20px;"> <p:menuitem value="step 1." actionListener="#{masterController.menuSales(preferencesController)}" update="mainPanel"/> <p:menuitem value="step 2." actionListener="#{masterController.menuCustomer(preferencesController)}" update="mainPanel"/> <p:menuitem value="step 3." actionListener="#{masterController.menuItem(preferencesController)}" update="mainPanel"/> <p:menuitem value="step 4"/> </p:steps> 

And the result will be like this:

enter image description here

I can click step 1, but not in steps 3 and 4. How do I enable a click for all steps?

+7
source share
3 answers

Wow, that's a good question!

I tried many things with the current API to execute it, but it looks like this is not possible with our current parameters.

To solve this problem, I wrote my own visualization tool for the Steps component:

Most of the code below is the same from PrimeFaces GitHub. I just changed a few things to solve this particular problem.

 import java.io.IOException; import java.util.ArrayList; import java.util.LinkedHashMap; import java.util.List; import java.util.Map; import javax.faces.FacesException; import javax.faces.component.UIComponent; import javax.faces.context.FacesContext; import javax.faces.context.ResponseWriter; import org.primefaces.component.api.AjaxSource; import org.primefaces.component.api.UIOutcomeTarget; import org.primefaces.component.steps.Steps; import org.primefaces.component.steps.StepsRenderer; import org.primefaces.model.menu.MenuItem; import org.primefaces.util.ComponentTraversalUtils; public class CustomStepsRenderer extends StepsRenderer { @Override protected void encodeItem(FacesContext context, Steps steps, MenuItem item, int activeIndex, int index) throws IOException { ResponseWriter writer = context.getResponseWriter(); String itemClass; if (steps.isReadonly()) { itemClass = (index == activeIndex) ? Steps.ACTIVE_ITEM_CLASS : Steps.INACTIVE_ITEM_CLASS; } else { if (index == activeIndex) { itemClass = Steps.ACTIVE_ITEM_CLASS; } else { itemClass = Steps.VISITED_ITEM_CLASS; } } String containerStyle = item.getContainerStyle(); String containerStyleClass = item.getContainerStyleClass(); if (containerStyleClass != null) { itemClass = itemClass + " " + containerStyleClass; } //header container writer.startElement("li", null); writer.writeAttribute("class", itemClass, null); writer.writeAttribute("role", "tab", null); if (containerStyle != null) { writer.writeAttribute("style", containerStyle, null); } encodeMenuItem(context, steps, item, activeIndex, index); writer.endElement("li"); } @Override protected void encodeMenuItem(FacesContext context, Steps steps, MenuItem menuitem, int activeIndex, int index) throws IOException { ResponseWriter writer = context.getResponseWriter(); String title = menuitem.getTitle(); String style = menuitem.getStyle(); String styleClass = this.getLinkStyleClass(menuitem); writer.startElement("a", null); writer.writeAttribute("tabindex", "-1", null); if (shouldRenderId(menuitem)) { writer.writeAttribute("id", menuitem.getClientId(), null); } if (title != null) { writer.writeAttribute("title", title, null); } writer.writeAttribute("class", styleClass, null); if (style != null) { writer.writeAttribute("style", style, null); } if (steps.isReadonly() || menuitem.isDisabled()) { writer.writeAttribute("href", "#", null); writer.writeAttribute("onclick", "return false;", null); } else { String onclick = menuitem.getOnclick(); //GET if (menuitem.getUrl() != null || menuitem.getOutcome() != null) { String targetURL = getTargetURL(context, (UIOutcomeTarget) menuitem); writer.writeAttribute("href", targetURL, null); if (menuitem.getTarget() != null) { writer.writeAttribute("target", menuitem.getTarget(), null); } } //POST else { writer.writeAttribute("href", "#", null); UIComponent form = ComponentTraversalUtils.closestForm(context, steps); if (form == null) { throw new FacesException("MenuItem must be inside a form element"); } String command; if (menuitem.isDynamic()) { String menuClientId = steps.getClientId(context); Map<String, List<String>> params = menuitem.getParams(); if (params == null) { params = new LinkedHashMap<String, List<String>>(); } List<String> idParams = new ArrayList<String>(); idParams.add(menuitem.getId()); params.put(menuClientId + "_menuid", idParams); command = menuitem.isAjax() ? buildAjaxRequest(context, steps, (AjaxSource) menuitem, form, params) : buildNonAjaxRequest(context, steps, form, menuClientId, params, true); } else { command = menuitem.isAjax() ? buildAjaxRequest(context, (AjaxSource) menuitem, form) : buildNonAjaxRequest(context, ((UIComponent) menuitem), form, ((UIComponent) menuitem).getClientId(context), true); } onclick = (onclick == null) ? command : onclick + ";" + command; } if (onclick != null) { writer.writeAttribute("onclick", onclick, null); } } writer.startElement("span", steps); writer.writeAttribute("class", Steps.STEP_NUMBER_CLASS, null); writer.writeText((index + 1), null); writer.endElement("span"); Object value = menuitem.getValue(); if (value != null) { writer.startElement("span", steps); writer.writeAttribute("class", Steps.STEP_TITLE_CLASS, null); writer.writeText(value, null); writer.endElement("span"); } writer.endElement("a"); } 

Then register this new renderer in the faces-config.xml file:

  <render-kit> <renderer> <component-family>org.primefaces.component</component-family> <renderer-type>org.primefaces.component.StepsRenderer</renderer-type> <renderer-class>YOUR_PACKAGE.CustomStepsRenderer</renderer-class> </renderer> </render-kit> 

Remember to change YOUR_PACKAGE to your CustomStepsRenderer package location.

After that, just create / redeploy the application and everything should work fine:

enter image description here

+5
source

Well, p:steps and p:wizard are components in the PrimeFaces component package that represent or indicate the step (s) in the workflow to manage several stages of the same form (step by step) to simplify the process and can be used interchangeably if you are correct understand the use (depending on the requirement).

To use the p:steps component, you must make sure that the next step will be displayed only when the current step is fully processed and the necessary data is collected. Suppose that the online shopping process, when the payment processing is the last, will be displayed if and only if you have any item in your basket and provided other information (if any).

The above script can also be implemented using the p:wizard component. If only the current step is partially processed, and the next step is displayed if the current step passes checks. However, the p:wizard component has the ability to override its default behavior by controlling the wizard flow, creating custom previous and next buttons using special action handlers and skipping validation to see the next steps.

+2
source

menuform: I can answer your question a little later, but I will post it, so if other people have the same problems, let it work for them.

I use JavaScript for the solution, so let this not be the solution you need:

 // That is your code. I added ids to capture them with the DOM. <p:steps activeIndex="3" styleClass="custom" readonly="false" style="padding: 20px;"> <p:menuitem value="step 1." actionListener="#{masterController.menuSales(preferencesController)}" update="mainPanel" id="step1"/> <p:menuitem value="step 2." actionListener="#{masterController.menuCustomer(preferencesController)}" update="mainPanel" id="step2"/> <p:menuitem value="step 3." actionListener="#{masterController.menuItem(preferencesController)}" update="mainPanel" id="step3"/> <p:menuitem value="step 4" id="step4"/> </p:steps> // Now we can make the script <script> // First of all, we will capture all the steps with the DOM (you can also work with jQuery, but I will post the solution with DOM in case you do not have your code prepared to jQuery) var step1 = document.getElementById("menuform:step1"); var step2 = document.getElementById("menuform:step2"); var step3 = document.getElementById("menuform:step3"); var step4 = document.getElementById("menuform:step4"); // Then, we are going to set the attributes href and onclick, and give them so style to make the elements look like proper links step1.setAttribute("href", "[url]"); step1.setAttribute("onclick", true"); step1.style.cursor = "pointer"; step2.setAttribute("href", "[url]"); step2.setAttribute("onclick", true"); step2.style.cursor = "pointer"; step3.setAttribute("href", "[url]"); step3.setAttribute("onclick", true"); step4.style.cursor = "pointer"; step4.setAttribute("href", "[url]"); step4.setAttribute("onclick", true"); step4.style.cursor = "pointer"; </script> 

It is important to change href and onclick (click event), because the 'steps' element changes both of them, this is how they look when you check the code from the console: - href = "#" - onclick = "return false;"

0
source

Source: https://habr.com/ru/post/1270765/


All Articles