J'ai des étapes Primefaces en utilisant la balise <p:steps> comme ci-dessous:

<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>

Et le résultat est comme ceci:

enter image description here

Je peux cliquer sur l'étape 1 mais pas sur les étapes 3 et 4. Comment puis-je activer le clic pour toutes les étapes?

8
Randyka Yudhistira 11 août 2017 à 07:25

2 réponses

Meilleure réponse

Wow, c'est une bonne question!

J'ai essayé beaucoup de choses avec l'API actuelle pour y parvenir, mais il semble que ce ne soit pas possible avec nos options actuelles.

Pour résoudre ce problème, j'ai écrit un moteur de rendu personnalisé pour le composant Steps:

La plupart du code ci-dessous est le même que celui du GitHub de PrimeFaces. Je viens de modifier quelques éléments pour résoudre ce problème spécifique.

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");
}

Ensuite, enregistrez ce nouveau moteur de rendu dans votre fichier faces-config.xml:

   <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>

N'oubliez pas de remplacer YOUR_PACKAGE par l'emplacement de votre package CustomStepsRenderer.

Après cela, créez / redéployez simplement votre application et tout devrait fonctionner correctement:

enter image description here

6
Bonifacio 26 janv. 2018 à 23:36

Menuform: Je peux répondre à votre question un peu tard, mais je la posterai donc si d'autres personnes ont le même problème, que cela fonctionne pour elles.

J'utilise JavaScript pour la solution, donc peut-être pas la solution dont vous avez besoin:

// 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 some 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>

Il est important de modifier href et onclick (événement de clic), car l'élément " étapes " modifie les deux, c'est comme si vous inspectez le code avec la console: - href = "#" - onclick = "return false;"

1
JairoEM 21 mai 2019 à 13:08