Я думаю, что проблема двоякая: есть обязательный валидатор и валидатор для переданного значения.В этом случае вам нужно позаботиться об обоих.
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).Увидеть? просто так сложно.