JSF - 如何在ui中保留瞬态值:立即采取行动后重复

时间:2016-01-27 17:02:00

标签: jsf jsf-2

我根据我的项目创建了一个非常简单的示例,以说明我的疑问。只是一种向一个人注册电话号码的方法。

MainController.java

private String name;
private List<Phone> phoneList;
// Getters and Setters

@PostConstruct
private void init() {
    phoneList = new ArrayList<>();
}

public static class Phone implements Serializable {

    private String number;
    // Getters and Setters

    @Override
    public String toString() {
        return number != null ? number : "null";
    }
}

public void add() {
    phoneList.add(new Phone());
}

public void save() {
    System.out.println("Name: " + name + "; " + phoneList.toString());
}

的index.xhtml

<h:form>
    <h:inputText value="#{mainController.name}" required="true" />
    <ui:repeat var="phone" value="#{mainController.phoneList}" varStatus="status">
        <h:inputText value="#{phone.number}" required="true" />
    </ui:repeat>
    <h:commandButton action="#{mainController.add()}" value="Add Phone" immediate="true" />
    <h:commandButton action="#{mainController.save()}" value="Save" />
</h:form>

在我的示例中,请注意添加的所有电话字段必须填写(required = true)。

问题是:当我输入名称并点击添加(添加手机)时,会保留该字段的值。但是,当我键入第一个手机并点击添加时,手机的值不会保留。对于组件ui:repeat中的所有字段都会发生这种情况。

有没有办法在即时请求后保留输入值,就像名称字段一样?

额外注意事项:我注意到的其他奇怪行为是在添加至少两个手机字段时,让第一个空白并填充第二个,然后保存表单。验证失败后(由于电话空白),单击“添加”将使所有字段都填充第二部电话的值。

Wildfly 9.0.2,JSF Api(Jboss)2.2.12

2 个答案:

答案 0 :(得分:3)

感谢@BalusC commentOmniFaces库有两个可以在这种情况下使用的标记处理程序。在这两种情况下,如果验证失败,将保留输入值。请注意,h:commandButton应该与<h:commandButton immediate="false" />

ignoreValidationFailed

在这种情况下,将忽略所有验证失败(包括转换器故障)。请注意,h:表单必须更改为o:form。此外,仍将显示失败消息,这可以通过在呈现的属性中放置适当的条件来解决。文件如下所示:

的index.xhtml

<o:form>
    <h:inputText value="#{mainController.name}" required="true" />
    <ui:repeat var="phone" value="#{mainController.phoneList}" varStatus="status">
        <h:inputText value="#{phone.number}" required="true" />
    </ui:repeat>
    <h:commandButton action="#{mainController.add()}" value="Add Phone">
        <o:ignoreValidationFailed />
    </h:commandButton>
    <h:commandButton action="#{mainController.save()}" value="Save" />
</o:form>
<h:messages rendered="#{facesContext.validationFailed}" />

skipValidators

在这种情况下,只会忽略验证失败(转换器仍会运行)。除转换器外,不会显示故障消息。请注意,此标记处理程序仅在2.3版本之后可用。文件如下所示:

的index.xhtml

<h:form>
    <h:inputText value="#{mainController.name}" required="true" />
    <ui:repeat var="phone" value="#{mainController.phoneList}" varStatus="status">
        <h:inputText value="#{phone.number}" required="true" />
    </ui:repeat>
    <h:commandButton action="#{mainController.add()}" value="Add Phone">
        <o:skipValidators />
    </h:commandButton>
    <h:commandButton action="#{mainController.save()}" value="Save" />
</h:form>

答案 1 :(得分:0)

我用于此问题的解决方案是为循环创建一个外部字段,该字段存储包含应保存的值的JSON。该字段位于循环外部,在每次尝试后正确保存值,并在必要时恢复缺失值。我使用两个函数JavaScript和JQuery库。

所以文件看起来像这样:

的index.xhtml

<h:outputScript library="jquery" name="jquery.min.js" />
<h:outputScript library="all" name="all.js" />

<h:form>
    <h:inputText value="#{mainController.name}" required="true" />
    <ui:repeat var="phone" value="#{mainController.phoneList}" varStatus="status">
        <h:inputText styleClass="savePhoneNumber" value="#{phone.number}" required="true" onchange="saveUiRepeatInput('#{allPhoneNumber.clientId}', 'savePhoneNumber')" />
    </ui:repeat>

    <h:inputHidden id="allPhoneNumber" binding="#{allPhoneNumber}" />
    <h:outputScript>loadUiRepeatInput('#{allPhoneNumber.clientId}', 'savePhoneNumber')</h:outputScript>

    <h:commandButton action="#{mainController.add()}" value="Add Phone" immediate="true" />
    <h:commandButton action="#{mainController.save()}" value="Save" />
</h:form>

all.js

function saveUiRepeatInput(inputAll, inputClass) {
    document.getElementById(inputAll).value = JSON.stringify($('.' + inputClass).map(function() { return this.value; }).get());
}

function loadUiRepeatInput(inputAll, inputClass) {
    var jsonAll = document.getElementById(inputAll).value;
    if (jsonAll) {
        var array = JSON.parse(jsonAll);
        $('.' + inputClass).each(function(i) { if (i < array.length) this.value = array[i]; });
    }
}

虽然工作完美(包括通过ajax,稍微改动一下),但它看起来像黑客,不是理想的解决方案。因此,如果任何人都可以帮助完全基于JSF的任何解决方案,我将不胜感激。感谢。