1

I want to automatically set the labels attributes for the UIInput components in my pages, to the HtmlOutputLabel components I already put, like the PrimeFaces developer did: http://cagataycivici.wordpress.com/2011/02/11/label-provider-for-jsf-input-components/ Only he did it using System Events, a feature available only in JSF-2.0, and my application is in JSF 1.2.

Is it possible to do it using JSF-1.2, with maybe a Phase Listener? What would be the drawbacks?

Thanks in advance!

UPDATE: This is what my attempt with a Phase Listener looks until now:

@Override
public void beforePhase(PhaseEvent event) {
    System.out.println("REGISTERING Label Provider");
    FacesContext context = event.getFacesContext();
    List<UIComponent> components = context.getViewRoot().getChildren();
    for (UIComponent uiComponent : components) {
        if (uiComponent instanceof HtmlOutputLabel) {
            HtmlOutputLabel outputLabel = (HtmlOutputLabel) uiComponent;
            System.out.println("CONFIGURING LABEL: " + outputLabel.getId());
            UIComponent target = outputLabel.findComponent(outputLabel
                    .getFor());
            if (target != null) {
                target.getAttributes().put("label", outputLabel.getValue());
            }
        }
    }
}

@Override
public PhaseId getPhaseId() {
    // Only listen during the render response phase.
    return PhaseId.RENDER_RESPONSE;
}

When I access the view, it never prints the section "CONFIGURING LABEL". What would be the right test to verify if a uiComponent is a HtmlOutputLabel? Or what am I doing wrong?

Elias Dorneles
  • 22,556
  • 11
  • 85
  • 107
  • Yes. What have you tried so far? – BalusC Jan 09 '12 at 19:04
  • I haven't really tried anything yet, I'm trying to figure out how to get the HtmlOutputLabel in a PhaseListener to execute before the APPLY_REQUEST_VALUES phase, and wondering if it is the right place to start... – Elias Dorneles Jan 09 '12 at 19:13
  • There's no means of an APPLY_REQUEST_VALUES phase during a GET request in JSF 1.x. Do it before RENDER_RESPONSE. – BalusC Jan 09 '12 at 19:17
  • wouldn't the validation messages using the labels have already been evaluated by then? – Elias Dorneles Jan 09 '12 at 19:19
  • They're not used in a GET request at all. In a POST request it doesn't matter as the same view will just be reused (for which you've already set the labels in render response of the initial GET request). – BalusC Jan 09 '12 at 19:27
  • Ah, understood! Thanks a lot, BalusC, you're always a great help! I'm having trouble to get the HtmlOutputLabels, I'm going to update the answer with my attempt... – Elias Dorneles Jan 09 '12 at 19:53

2 Answers2

1

The UIViewRoot#getChildren() only returns the direct children of the view root, not all children as you seem to expect. You need to iterate through the children of each child recursively as well.

Something like this:

@Override
public void beforePhase(PhaseEvent event) {
    applyLabels(event.getFacesContext().getViewRoot().getChildren());
}

private static void applyLabels(List<UIComponent> components) {
    for (UIComponent component : components) {
        if (component instanceof HtmlOutputLabel) {
            // ...
        } else {
            applyLabels(component.getChildren()); // Reapply on its children.
        }
    }
}

Since JSF 2.0 the above is by the way convenienced with the UIComponent#visitTree() method which follows the visitor pattern so that you just have to make a single call.

BalusC
  • 1,082,665
  • 372
  • 3,610
  • 3,555
  • Ouch, my mistake! I've fixed it now, works beautifully! Thanks a lot, man! – Elias Dorneles Jan 09 '12 at 20:15
  • Hey, BalusC! I had to switch to before APPLY_REQUEST_VALUES phase, cause sometimes in a GET request the view root children list was coming empty. Do you have any idea why is that? Do you think doing it can be a problem doing it in this phase? Thanks a lot! – Elias Dorneles Jan 10 '12 at 19:47
  • When exactly is "sometimes"? This will indeed happen on initial requests without pre render view events in JSF2, but not in JSF1 as far as I know. What JSF impl/version exactly are you using? Doing during apply request values should after all be good enough. You need this information during POST requests only anyway. – BalusC Jan 10 '12 at 19:55
  • I wish I knew why it is "sometimes"... Yesterday it seemed to be working, today morning it wasn't. :/ Know something I can test? I'm using mojarra 1.2_15 (latest for 1.2 branch, as far as I know). Thanks a lot for your help! – Elias Dorneles Jan 10 '12 at 20:56
-1
<h:outputText value="#{yourVO.tax}" /> 

Create a data transfer object (DTO) object in your action class and declare a string variable tax in the DTO, so that you can use it to set labels in your action class.

BalusC
  • 1,082,665
  • 372
  • 3,610
  • 3,555
Abhi
  • 6,471
  • 6
  • 40
  • 57
  • Perhaps you didn't see the real problem at all. This way you've still to define the value twice. – BalusC Jan 09 '12 at 19:03
  • @Abhi_sr: I think you misunderstood my problem. I just don't want to repeat the labels in the h:outputLabel AND in the h:inputXXX associated. – Elias Dorneles Jan 09 '12 at 19:15