условный валидатор не работает, как это настроить? - PullRequest
0 голосов
/ 26 сентября 2018

На моей странице xpage я определил валидатор для элемента управления inputtext:

<xp:inputText id="cv"
    disabled="#{!employeeBean.employee.editable}"
    value="1"
    validator="#{employeeValidator.valAttachments}">
    <xp:this.required><![CDATA[#{javascript:return submittedBy("btnSendToHR")}]]></xp:this.required>
    <xp:this.validators>
        <xp:validateRequired
            message="No CV added">
        </xp:validateRequired>
    </xp:this.validators>
</xp:inputText>

Валидатор очень простой и выглядит следующим образом:

public void valAttachments(FacesContext facesContext, UIComponent component, Object value) {
    // my business logic here
    String msg = null;
    msg = "//collecting string from properties file";
    FacesMessage message = new FacesMessage(msg);
    throw new ValidatorException(message);  
}

Сейчас я пытаюсьсделать мой валидатор условным для кнопки, которая вызвала отправку (submitBy ("btnSendToHR")) (вдохновение, которое я нашел в этом посте http://dontpanic82.blogspot.com/2010/03/xpages-making-validation-behave.html):

<xp:this.validator><![CDATA[#{javascript://emploteeValidator.valAttachments
if (true == submittedBy("btnSendToHR")){
    importPackage(se.bank.app.test);
    var mv = new se.bank.app.test.EmployeeValidator();
    mv.valAttachments(facesContext, getComponent("cv"),"0" );
}}]]></xp:this.validator>

Я вижу, что метод вызывается (например, когда я включаю в метод System.out.println (). Пример:

Ошибка при выполнении выражения действия JavaScript Ошибка интерпретатора сценария, строка = 5, столбец = 12: Ошибка вызова метода

'valAttachments (com.ibm.xsp.domino.context.DominoFacesContext, com.ibm.xsp.component.xp.XspInputText, string)' в классе Java 'se.bank.app.test.EmployeeValidator'из valAttachments: cv валидации теста, отправленное значение = 0

Может кто-нибудь объяснить, как я могу сделать валидатор в зависимости от идентификатора отправки (кнопка)?

Ответы [ 2 ]

0 голосов
/ 27 сентября 2018

Я думаю, что проблема двоякая: есть обязательный валидатор и валидатор для переданного значения.В этом случае вам нужно позаботиться об обоих.

XPages читы с требуемым валидатором в том смысле, что он динамически подключает его на этапе рендеринга.Это связано с тем, что не запускается валидатор, если входное значение пусто для инфраструктуры JSF, из которой распространяется XPages.Это означает, что если у вас есть валидатор, но у вас нет required=true на входе, валидатор не будет работать, если входное значение пустое.

Насколько я знаю, требуемый пользовательский валидатор может 'не использовать без использования уродливых обходных путей.Но, как вы пытались это сделать, вы можете поиграть с переворотом значения required=, поскольку оно будет оцениваться как в запросе GET, так и в запросе POST.

С учетом сказанного, хотя я не фанат того, что яЯ собираюсь сказать - я бы, вероятно, спросил себя, почему я хочу сделать UX / UI таким образом, вы можете связать кнопки и работать с идентификаторами проще.Рассмотрим следующее:

<xp:div id="containerForm">
    <xp:inputText id="inputText1" value="#{viewScope.whatever}"
        required="#{javascript:param['$$xspsubmitid'] === getClientId(eventSubmit.id)}" />

    <xp:button id="buttonSubmitValidate" value="Submit">
        <xp:eventHandler id="eventSubmit" binding="#{eventSubmit}" event="onclick"
            submit="true" execMode="partial" execId="containerForm" refreshMode="partial"
            refreshId="messages" />
    </xp:button>

    <xp:button id="buttonSubmitNoValidate" value="Submit No Validate">
        <xp:eventHandler event="onclick" submit="true"
            execMode="partial" execId="containerForm" refreshMode="partial"
            refreshId="messages" />
    </xp:button>
</xp:div>

<xp:div id="messages">
    <xp:messages globalOnly="false" />
</xp:div>

Здесь я использую несколько вещей, унаследованных от концепции SSJS (к сожалению, хотя и немного).В свойстве required я получаю eventHandler идентификатор клиента , создавая его дескриптор через свойство binding.Другими словами, этот обработчик события component будет доступен под именем переменной eventSubmit.Но eventSubmit.id вернет идентификатор компонента на стороне сервера, который мы не можем оценить, потому что $$xspsubmitid будет содержать его аналог на стороне клиента.Чтобы получить идентификатор клиента для компонента, нам нужно вызвать getClientId(eventSubmit.id).На данный момент у меня есть все, что мне нужно, чтобы правильно оценить, хочу ли я требовать поле или нет, сравнивая такое значение с тем, что было передано в параметре запроса POST $$xspsubmitid.

Обработчик события другой кнопки, безусловно, будетиметь другой динамически сгенерированный идентификатор клиента, и поэтому, если вы отправите форму, нажав на кнопку, к которой она прикреплена, она не запустит необходимый валидатор.Это самый быстрый способ подсчитать ваш результат.

Однако, если конфигурация более сложная, скажем, у вас есть дополнительные валидаторы, связанные с входом, я бы предложил что-то другое:

<xp:inputText id="inputText1" value="#{viewScope.whatever}"
    required="#{javascript:validator.shouldBeFired(this)}" validator="#{validator.requireOtherCondition}">
    <xp:this.attrs>
        <xp:attr name="data-require-on-submit-id" value="#{id:eventSubmit}" />
    </xp:this.attrs>
</xp:inputText>

Здесь я пытаюсь не повторяться.Я использую bean-компонент validator, чтобы скрыть оценку того, что мне нужен идентификатор обработчика событий или нет.Так как мне все еще понадобится этот обработчик события, идентифицирующий метод валидатора, который я легко использую - это называется перехватом, LOL - сохраните его как свойство ввода.

На этом этапе свойство required и дополнительный валидатор могут полагаться наЭто.Как?

Сначала я просто хочу использовать вспомогательный класс для методов, которые можно использовать в моем приложении - они могут пригодиться в другом месте, кто знает ...

public enum Helper {
;

    public static Attr getComponentAttr(UIComponent component, String key) {
        if (component instanceof FacesAttrsObject) {
            FacesAttrsObject attrsObj = (FacesAttrsObject) component;
            List<Attr> attrs = attrsObj.getAttrs();

            if (attrs != null) {
                for (Attr attr : attrs) {
                    if (attr.getName().equals(key)) {
                        return attr;
                    }
                }
            }
        }

        return null;
    }

    @SuppressWarnings("unchecked")
    public static Map<String, String> getRequestParameterMap(FacesContext facesContext) {
        return (Map<String, String>) facesContext.getExternalContext().getRequestParameterMap();
    }

    public static String getSubmitId(FacesContext facesContext) {        
        return getRequestParameterMap(facesContext).get("$$xspsubmitid");
    }

}

Я надеюсь, чтоПриведенные выше методы приводят довольно объяснительно.На этом этапе я пишу методы bean-компонента validator:

public class ValidatorBean implements Serializable {

    private static final long serialVersionUID = 1L;

    public void requireOtherCondition(FacesContext facesContext, UIComponent component, Object value)
            throws ValidatorException {
        if (shouldBeFired(facesContext, component) && String.valueOf(value).length() < 3) {
            FacesMessage message = new FacesMessage("Hey, it's too short!");

            throw new ValidatorException(message);
        }
    }

    public boolean shouldBeFired(UIComponent component) {
        return shouldBeFired(FacesContext.getCurrentInstance(), component);
    }

    public boolean shouldBeFired(FacesContext facesContext, UIComponent component) {
        Attr attr = Helper.getComponentAttr(component, "data-require-on-submit-id");

        return attr != null && attr.getValue().equals(Helper.getSubmitId(facesContext));
    }

}

Метод shouldBeFired будет проходить по входной коллекции атрибутов в поисках атрибута с именем data-require-on-submit-id.Если и когда он находит его, он сравнивает его с текущим переданным идентификатором, повторным через метод класса Helper getSubmitId.По сути, это то же самое, что мы делали раньше непосредственно на странице xsp с SSJS.

Метод requireOtherCondition - это просто тупой валидатор, который будет запускаться только при выполнении того же условия для атрибута required.Если этого не произойдет, то не будет никакого запуска валидатора.Если он выполняет валидатор, вы можете запустить существующий или просто быстро сделать его там (в моем случае он срабатывает, если длина входного значения меньше 3).Увидеть? просто так сложно.

0 голосов
/ 26 сентября 2018

Может быть, вы пытаетесь что-то более сложное, чем вам нужно.Валидатор уже имеет доступ к компоненту, запускающему проверку.См. UIComponent component является одним из параметров.Это может быть xp: eventHandler, но оттуда getParent().Это может позволить вам получить все, что вам нужно.

Если вы хотите избежать кодирования в валидаторе, this.getParent() получает компонент в SSJS eventHandler.Например, вы можете передать параметр для установки действительного значения на основе идентификатора.

...