使 Primefaces 的数据表行在行版本上无效

2024-04-29

我正在使用 JSF 2.1 + Primefaces 5.1 开发一个网络应用程序。我有一个带有行版本的数据表,每行有 2inputText, 2 selectOneMenu and 1 selectBooleanCheckbox。我想在单击复选图标时执行一些业务逻辑验证:它将验证 2 的值selectOneMenus。为此,我创建了一个与第二个关联的自定义验证器selectOneMenu验证这两个值:

<p:dataTable id="users_table_id" var="user" value="#{usersBean.users}" rowKey="#{user.id}" paginator="true"
            paginatorTemplate="{CurrentPageReport}  {FirstPageLink} {PreviousPageLink} {PageLinks} {NextPageLink} {LastPageLink} {RowsPerPageDropdown}"
               rowsPerPageTemplate="5,10,15" emptyMessage="#{msgs.no_records}" sortBy="#{user.id}" sortOrder="ascending" rows="15" editable="true">
            <f:facet name="header">
                #{msgs.users}               
            </f:facet>
            <p:ajax event="rowEdit" listener="#{usersBean.onRowEdit}" update=":users_form_id:growl"/>
            <p:ajax event="rowEditInit" listener="#{usersBean.onRowEditInit}" update=":users_form_id:growl"/>
            <p:ajax event="rowEditCancel" listener="#{usersBean.onRowEditCancel}" update=":users_form_id:growl"/>
            <p:column headerText="#{msgs.id}" sortBy="#{user.id}" styleClass="centered-column">
                #{user.id}
            </p:column>          
            <p:column headerText="#{msgs.description}" sortBy="#{user.description}" styleClass="centered-column">
                <p:cellEditor>
                    <f:facet name="output">#{user.description}</f:facet>
                    <f:facet name="input"><p:inputText value="#{user.description}" styleClass="editable-cell"/></f:facet>
                </p:cellEditor>
            </p:column>          
            <p:column headerText="#{msgs.password}" sortBy="#{user.password}" styleClass="centered-column">
                <p:cellEditor>
                    <f:facet name="output">#{user.password}</f:facet>
                    <f:facet name="input"><p:inputText value="#{user.password}" styleClass="editable-cell"/></f:facet>
                </p:cellEditor>
            </p:column>
            <p:column headerText="#{msgs.sending_system}" sortBy="#{user.playerIn.description}" styleClass="centered-column">
                <p:cellEditor>
                    <f:facet name="output">#{user.playerIn.description}</f:facet>
                    <f:facet name="input">
                        <p:selectOneMenu binding="#{userPlayerInComponent}" styleClass="editable-cell" id="users_table_sending_system_id" value="#{user.playerIn}" effectSpeed="fast" filter="true" filterMatchMode="contains" converter="#{playerConverter}">
                            <f:selectItem itemLabel="#{msgs.select_option}" itemValue="#{null}" noSelectionOption="true"/>
                            <f:selectItems value="#{usersBean.players}" var="player" itemValue="#{player}" itemLabel="#{player.description}"/>
                        </p:selectOneMenu>
                    </f:facet>
                </p:cellEditor>
            </p:column> 
            <p:column headerText="#{msgs.receiving_system}" sortBy="#{user.playerOut.description}" styleClass="centered-column">
                <p:cellEditor>
                    <f:facet name="output">#{user.playerOut.description}</f:facet>
                    <f:facet name="input">
                        <p:selectOneMenu styleClass="editable-cell" id="users_table_receiving_system_id" value="#{user.playerOut}" effectSpeed="fast" filter="true" filterMatchMode="contains" converter="#{playerConverter}">
                            <f:selectItem itemLabel="#{msgs.select_option}" itemValue="#{null}" noSelectionOption="true"/>
                            <f:selectItems value="#{usersBean.players}" var="player" itemValue="#{player}" itemLabel="#{player.description}"/>

                            <f:validator validatorId="userValidator"/>
                            <f:attribute name="userPlayerInComponent" value="#{userPlayerInComponent}"/>
                        </p:selectOneMenu>
                    </f:facet>
                </p:cellEditor>
            </p:column>                                     
            <p:column headerText="#{msgs.active}" sortBy="#{user.active}" styleClass="centered-column">
                <p:cellEditor>
                    <f:facet name="output"><p:selectBooleanCheckbox value="#{user.active}" disabled="true"/></f:facet>              
                    <f:facet name="input"><p:selectBooleanCheckbox value="#{user.active}"/></f:facet>
                </p:cellEditor>
            </p:column>
            <p:column styleClass="datatable-row-editor">
                <p:rowEditor/>
            </p:column>
            <f:facet name="footer">
            </f:facet>      
        </p:dataTable>
@FacesValidator("userValidator")
public class UserValidator implements Validator {

    private static final Logger logger =  LogManager.getLogger(UserValidator.class);

    @Override
    public void validate(FacesContext context, UIComponent component, Object value) throws ValidatorException {
        logger.entry(context, component, value);

        if (value == null) {
            return; // Let required="true" handle.
        }

        UIInput userPlayerInComponent = (UIInput)component.getAttributes().get("userPlayerInComponent");
        if (!userPlayerInComponent.isValid()) {
            return; // Already invalidated. Don't care about it then.
        }

        DtoPlayer playerIn = (DtoPlayer)userPlayerInComponent.getValue();
        if (playerIn == null) {
            return; // Let required="true" handle.
        }

        DtoPlayer playerOut = (DtoPlayer)value;

        UsersBean usersBean = context.getApplication().evaluateExpressionGet(context, "#{usersBean}", UsersBean.class);

        BigDecimal userId = usersBean.getUserEditingId();
        logger.info(userId + " - " + playerIn.getDescription() + " - " + playerOut.getDescription());

        for (DtoUser dtoUser : usersBean.getUsers()) {
            if (!userId.equals(dtoUser.getId()) && dtoUser.getPlayerIn().equals(playerIn) && dtoUser.getPlayerOut().equals(playerOut)) {
                logger.info("Invalidating...");
                userPlayerInComponent.setValid(false);              
                FacesContext.getCurrentInstance().validationFailed();
                throw new ValidatorException(new FacesMessage("BOOM!"));
            }
        }
        logger.exit();
    }
}

我期待的是,当验证失败时(并且ValidatorException被抛出),数据表行将保持编辑模式,并且两个selectOneMenus 以红色突出显示。但发生的情况是该行退出编辑模式,保留旧值。如果我再次编辑它,它会显示提交的值,并且无效的单元格会标记为红色。只要我尝试提交无效值,这种行为就会持续下去。如果我关闭编辑模式,无效值将被丢弃,并且该行仅保留旧值(无论是在查看模式还是编辑模式下)。

我该如何解决这个问题?来自Primefaces 的展示 http://www.primefaces.org/showcase/ui/data/datatable/edit.xhtml,可以看到,当您尝试提交(比方说)年份单元格中包含字母字符的字符串时,该行将保持编辑模式并突出显示。我想实现同样的行为。


None

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

使 Primefaces 的数据表行在行版本上无效 的相关文章

随机推荐