Patrick Kwinten
Patrick Kwinten

Reputation: 2048

XPages / JSF possible to invoke validation from code?

On an xpage I have the validation bound to the status of an object (draft,for approval, approved).

<xp:inputText
    id="inpHighRiskCountry" styleClass="inputEscalation"
    value="#{matterBean.matter.escHighRisk}"
    validator="#{matterValidators.valEscHighRiskCountry}"
    disabled="#{!matterBean.matter.editable}">
    <xp:this.attrs>
        <xp:attr name="placeholder"
            value="#{matter.gen_EnterCountry}" />
    </xp:this.attrs>
    <xp:this.validators>
        <xp:validateRequired
            message="#{matter.msg_valid_esc_high_risk}" />
    </xp:this.validators>
    <xp:this.required><![CDATA[#{!(matterBean.matter.status eq "For approval")}]]></xp:this.required>
</xp:inputText>

In status draft (the default value) NO validation is required. Before sending to approval I want the validation to occur.

How can I initiate this? (e.g. initiate at any time validation)

Now I have under a "Send for approval" button a function that tries to save the object in backend. So first it sets the status to "For approval", saves the object. I would like to have it "execute validation", set the status, save the object.

I am webifying an existing application so I am doubtful if I can introduce an "in between" status.

Upvotes: 0

Views: 73

Answers (1)

shillem
shillem

Reputation: 1260

I think you are mistakingly mixing a couple of things that should be kept separate: UI interaction and business logic.

It's true UI interaction attempts to mimic the business logic by requiring some certain values to be present and valid before proceeding. But as you can see it cannot always be done perfectly because business logic might demand more elaborate checks, like in this case.

However I don't see where the problem is. JSF can still help you to return the error on the input you need it. If I were to attack the problem I would remove the required attribute - and validator text - to be checked at the action level, as you already figured out, just that I would do it before saving the doc and not as a consequence of the failed save.

What you can simply do is either to attach it as a general error or, if you still want to bind it to the specific input, to do that.

Let's take the second approach:

<xp:inputText binding="#{inpHighRiskCountry}"
    id="inpHighRiskCountry" styleClass="inputEscalation"
    value="#{matterBean.matter.escHighRisk}"
    readonly="#{!matterBean.matter.editable}">
    <xp:this.attrs>
        <xp:attr name="placeholder"
            value="#{matter.gen_EnterCountry}" />
    </xp:this.attrs>
</xp:inputText>

<xp:message for="inpHighRiskCountry" />

<xp:button id="button1" value="Save">
    <xp:eventHandler event="onclick" submit="true"
        action="#{matterBean.sendToApproval}" />
</xp:button>

For the inputText I set the binding option because, I think, it will be easier from the bean method to get hold of the input. Then I placed the xp:message component for the displaying the input error and a stupid button with the hypothetical call to the send to approval operation.

public void sendToApproval() {
    if (...) { // check your escHighRisk logic here
        FacesContext facesContext = FacesContext.getCurrentInstance();
        UIComponent component = facesContext
                .getApplication()
                .getVariableResolver()
                .resolveVariable(facesContext,
                "inpHighRiskCountry");

        String errorSummary = "Your error here";
        FacesUtil.addMessage(
                facesContext,
                FacesMessage.SEVERITY_ERROR,
                component,
                errorSummary,
                null;

        return;
    }

    // Code would continue here with saving or whatever else
}

Upvotes: 1

Related Questions