Есть ли способ обновить компонент, даже если сбой JSF на этапе проверки процесса - PullRequest
3 голосов
/ 27 февраля 2012

У меня есть входной текст с атрибутом required=true, как показано ниже

<h:panelGrid columns=2>
   <h:panelGroup id="ccm">
      <p:inputText id="txtCCMNumber" value="#{setupView.selectedCCM}"
                 required="true" requiredMessage="Required">
          <p:ajax event="blur" listener="#{setupView.handleLooseFocusCCMTextbox()}"
              update=":setupForm:ccm :setupForm:ccmMsg"/>
      </p:inputText>
      <h:outputText value="Duplicated" id="ccmExisted"
                 styleClass="ui-message-error ui-widget ui-corner-all"
                 rendered="#{setupView.ccmNameExisted}"/>
      <h:graphicImage id="ccmNotExist" url="resources/images/check-icon.png"
                    rendered="#{setupView.ccmNameUnique}"
                    width="18"/>
   </h:panelGroup>
   <p:message for="txtCCMNumber" id="ccmMsg" display="text"/>
</h:panelGrid>

Итак, мое требование: если значение пустое, оно будет отображать Required, так как required=true, оно должно завершиться ошибкой на этапе проверки процесса. Если значение является уникальным, отобразите изображение check, если дублировано, отобразите текст Duplicated. Проблема, с которой я сталкиваюсь, заключается в том, что после того, как я что-то набираю и убираю табуляцию (скажем, я набираю что-то уникальное), оно отображает изображение check, затем я стираю текст и снова убираю табуляцию, теперь появляется текст Required , но так же check изображение. Моя теория состоит в том, что на этапе Process validation он завершается неудачей из-за пустого значения, поэтому на этапе обновления компонента он не вызывает метод handleLooseFocusCCMTextbox(), который установит логическое значение ccmNameUnique в false. Есть ли способ это исправить?

ПРИМЕЧАНИЕ : handleLooseFocusCCMTextbox () просто включает и выключает логическое значение для отображения изображения check или Duplicated текста.

Ответил . Создать класс Validator, удалить обязательно = true

public void validate(FacesContext fc, UIComponent uic, Object value)
        throws ValidatorException {
     FacesContext context = FacesContext.getCurrentInstance();
     SetupView setupView = (SetupView) context.getApplication().
           evaluateExpressionGet(context, "#{setupView}", SetupView.class);
     if (value == null || value.toString().isEmpty()) {
        setupView.setCcmNameUnique(false);
        FacesMessage message = new FacesMessage();
        message.setSeverity(FacesMessage.SEVERITY_ERROR);
        message.setSummary("Error");
        message.setDetail("Required");
        //This will end up in <p:message>
        throw new ValidatorException(message);
     }
     String rootPath = setupView.getRootPath();
     File rootFolder = new File(rootPath);
     if (rootFolder.exists() && rootFolder.canRead()) {
        List<String> folderNames = Arrays.asList(new File(rootPath).list());
        if (folderNames.contains(value.toString())) {
           setupView.setCcmNameUnique(false);
           FacesMessage message = new FacesMessage();
           message.setSeverity(FacesMessage.SEVERITY_ERROR);
           message.setSummary("Error");
           message.setDetail("Duplicate");
           //This will end up in <p:message>
           throw new ValidatorException(message);
        } else {
           setupView.setCcmNameUnique(true);
        }
     } else {
        logger.log(Level.SEVERE, "Please check the root folder path as "
              + "we cannot seems to see it. The path is {0}", rootPath);
     }
}

1 Ответ

2 голосов
/ 27 февраля 2012

Вы хотите использовать валидатор вместо прослушивателя действий.

<p:inputText id="txtCCMNumber" value="#{setupView.selectedCCM}"
    required="true" requiredMessage="Required"
    validator="#{setupView.validateDuplicateCCM}">
    <p:ajax event="blur" update="ccm ccmMsg" />
</p:inputText>

с

public void validateDuplicateCCM(FacesContext context, UIComponent component, Object value) throws ValidatorException {
    if (value == null || value.toString().isEmpty()) {
        return; // Let required="true" handle.
    }

    // ...

    if (duplicate) {
        ((UIInput) component).setValid(false);
        ccmNameExisted = true;
        // I'd rather throw ValidatorException instead of above two lines here so that it ends up in <p:message>
    } else {
        ccmNameUnique = true;
    }
}
...