How to create a picklist in JSF? Tried moving items using JS/jQuery, but submit errors with “Validation Error: Value is not valid”

丶灬走出姿态 提交于 2019-11-29 16:09:34
BalusC

To the point, your concrete problem is caused by the mistake that you filled listbox items using JavaScript/jQuery instead of JSF. This way JSF is never been made aware of the new items added by JavaScript. You need to fill the listbox items using JSF instead of JavaScript/jQuery.

When you submit a form with an UISelectOne/UISelectMany component, then JSF will always compare the submitted value to the list of available items from <f:selectItem(s)>. If the submitted value is not contained in the list of available items, then you will get exactly this Validation Error: Value is not valid error. This is part of builtin safeguard against tampered/attacked requests. The client should not be able to submit a item which the server has not specified.

Changing the available items in JavaScript/jQuery side does not automagically also change the available items in JSF <f:selectItems> side as well. You really need to change the available items in JSF side. You can easily use the JSF 2.x ajax powers for this. Here's a concrete kickoff example:

<h:form>
    <h:panelGrid columns="3">
        <h:selectManyListbox id="left" value="#{bean.leftSelected}">
            <f:selectItems value="#{bean.leftAvailable}" />
            <f:ajax event="dblclick" render="left right" listener="#{bean.leftToRight}" />
        </h:selectManyListbox>
        <h:panelGroup>
            <h:commandButton value="left to right">
                <f:ajax execute="left" render="left right" listener="#{bean.leftToRight}" />
            </h:commandButton>
            <br/>
            <h:commandButton value="right to left">
                <f:ajax execute="right" render="left right" listener="#{bean.rightToLeft}" />
            </h:commandButton>
        </h:panelGroup>
        <h:selectManyListbox id="right" value="#{bean.rightSelected}">
            <f:selectItems value="#{bean.rightAvailable}" />
            <f:ajax event="dblclick" render="left right" listener="#{bean.rightToLeft}" />
        </h:selectManyListbox>
    </h:panelGrid>
</h:form>

with

@ManagedBean
@ViewScoped
public class Bean {

    private List<String> leftSelected;
    private List<String> leftAvailable;
    private List<String> rightSelected;
    private List<String> rightAvailable;

    @PostConstruct
    public void init() {
        leftAvailable = new ArrayList<String>(Arrays.asList("one", "two", "three", "four", "five"));
        rightAvailable = new ArrayList<String>();
    }

    public void leftToRight() {
        leftAvailable.removeAll(leftSelected);
        rightAvailable.addAll(leftSelected);
        leftSelected = null;
    }

    public void rightToLeft() {
        rightAvailable.removeAll(rightSelected);
        leftAvailable.addAll(rightSelected);
        rightSelected = null;
    }

    // Add/generate getters+setters. Note: the "available" lists doesn't need setters.
}

That's all. No JS/jQuery mess necessary. When using custom non-string objects don't forget to provide a proper converter and equals() method.

See also:

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!