0

I'm new to PrimeFaces and when I try to use <p:inplace> with <f:facet> for multiple input fields, it still toggles back even though the validation fails.

The code is as following:

<p:inplace editor="true">
  <f:facet name="output">
    <h:outputText value="Hello Inplace" />
  </f:facet>
  <f:facet name="input">
    <p:inputText value="#{myBean.name}" required="true" />
    <p:inputText value="#{myBean.age}" required="true" />
  </f:facet>
</p:inplace>

So when I leave 2 input fields blank, it still toggles back to the output facet, while it should have kept the same with red borders. Please help me out. Thank you.

Tiny
  • 27,221
  • 105
  • 339
  • 599
  • Your code looks considerably different than the examples shown on the [PrimeFaces showcase](http://www.primefaces.org/showcase/ui/input/inplace.xhtml). They're using labels and inputText without defining facets. I see that facets _are_ used in some of the showcase examples, but do things work as expected if you follow the example more closely, i.e. define each `inputText` in its own `inplace` component? – DavidS Apr 20 '15 at 19:01
  • 1
    In Primefaces showcase they still use , you can check again. The idea is when I click on one facet, it will open the other facet. – Beautiful Life Apr 22 '15 at 04:15
  • Yes, I saw that they are using facets, but they are not using facets they way you are attempting to. Named facets are a part of a component's API: their usage is constrained to the API designer's intent. For example, a `dataTable` can have a facet named "header" and "footer", but it is the component author that decides what to do with these facets. As the PrimeFaces showcase does not show an example where they nest multiple input components inside a facet named "input", you have no assurance that it's going to behave the way you hope it will. – DavidS Apr 22 '15 at 04:42

1 Answers1

2

I believe there is a bug in inplace.isValid() related to the use of facets as I'm seeing the same issue. Here is the relevant code from the encodeMarkup method in InplaceRenderer. As you can see it does expect named facets of input and output.

protected void encodeMarkup(FacesContext context, Inplace inplace) throws IOException {
    // ...

    boolean validationFailed = context.isValidationFailed() && !inplace.isValid();
    String displayStyle = validationFailed ? "none" : "inline";
    String contentStyle = validationFailed ? "inline" : "none";

    UIComponent outputFacet = inplace.getFacet("output");
    UIComponent inputFacet = inplace.getFacet("input");

    // ...
}

You can see the full code here: https://github.com/primefaces/primefaces/blob/master/src/main/java/org/primefaces/component/inplace/InplaceRenderer.java

Looking at isValid in InplaceTemplate, it looks like it only attempts validation on the immediate children of inplace and does not recurse down through its other descendants (unless getFacetsAndChildren flattens the descendant tree, which I'm researching now). Since facets aren't instances of EditableValueHolder then it doesn't even attempt validation on them and returns true. Here is the entire isValid method.

public boolean isValid() {
    boolean valid = true;

    for(Iterator<UIComponent> it = this.getFacetsAndChildren(); it.hasNext();) {
        UIComponent component = it.next();
        if(component instanceof EditableValueHolder && !((EditableValueHolder) component).isValid()) {
            valid = false;
            break;
        }
    }

    return valid;
}

You can see the full code at https://github.com/primefaces/primefaces/blob/master/src/main/java-templates/org/primefaces/component/inplace/InplaceTemplate.java

I don't know as there's a solution to this beyond submitting a bug.

EDIT

<p:inplace id="inplace" editor="true">
    <f:facet name="output">
        <h:outputText value="#{bean.value}" />
    </f:facet>
    <f:facet name="input">
        <p:inputText id="input" value="#{bean.value}" required="true" requiredMessage="Required field message goes here" />
        <p:message for="input" />
    </f:facet>
</p:inplace>

Updating it to something like this got us closer so it is possible that having multiple components within the facet is the problem.

<p:inplace id="inplace" editor="true">
    <p:ajax event="save" update="message" />
    <f:facet name="output">
        <h:outputText value="#{bean.value}" />
    </f:facet>
    <f:facet name="input">
        <p:inputText id="input" value="#{bean.value}" required="true" requiredMessage="Required field message goes here" />
    </f:facet>
</p:inplace>
<p:message id="message" for="input" />

Unfortunately this still leaves a bit to be desired related to resetting the field and message when hitting cancel, but at least it's a step in the right direction for us.

JDavis
  • 76
  • 4
  • I still don't think this is any kind of "bug"; it's a misunderstanding and misuse of the API. Nothing in the PrimeFaces showcase or documentation suggests that the OP's usage is supported. Named facets are a part of a component's API. All you've discovered is that the API doesn't support a feature you would like it to. It's as if you tried to add named Facet "sidebar" to a datatable: it's not going to just work. – DavidS May 07 '15 at 22:06
  • According to BalusC, a Facet can have only [one child](http://stackoverflow.com/a/9731130/201891), which reflects the proper use of Facets, which is as a way of providing extra information to a component. – DavidS May 07 '15 at 22:11
  • 1
    Yeah, my edit was intended to make that point. We tried adding multiple fields and other components, as well as nesting components inside of other containers like a panel, all with the same result. It may not be a bug, but it is an unfortunate limitation. – JDavis May 08 '15 at 12:02