Search code examples
javajsfrichfaces

Uncaught TypeError: Cannot read property 'action' of null


I have two selectOneMenus and want to change the values of the second if the value in the first menu has been changed and backwards. The two menus are filled with the years from 1980 to 2012. If I select 1990 in the first menu I would like to have only the years 1990-2012 in the second menu.

But if I select a different value nothing happens and I get following message when I analyse this element:

Uncaught TypeError: Cannot read property 'action' of null    
A4J.Query 
A4J.AJAX.PrepareQuery 
A4J.AJAX.Submit 
onchange

Here is what I have:

<%-- Year filter --%>
<h:selectOneMenu id="minYear" value="#{statistics.minYear}" 
                 style="width: 75px">
    <f:selectItems value="#{statistics.minYearValues}" />
    <a4j:support event="onchange" action="#{statistics.minYearChanged}"
                 reRender="maxYear"/>
</h:selectOneMenu>

<h:selectOneMenu id="maxYear" value="#{statistics.maxYear}" 
                 style="width: 75px">
    <f:selectItems  value="#{statistics.maxYearValues}"/>
    <a4j:support event="onchange" action="#{statistics.maxYearChanged}"
                 reRender="minYear" />
</h:selectOneMenu>
<%-- end year filter--%>

And here the managed bean:

public List getMinYearValues() {
    this.minYear = MIN_YEAR;
    this.minYearValues = fillYearValues(MIN_YEAR, maxYear);
    return minYearValues;
}

public List getMaxYearValues() {
    int min = this.minYear;
    this.maxYearValues = fillYearValues(min, maxYear);
    return maxYearValues;
}

private List fillYearValues(int min, int max) {
    List values = new ArrayList();
    for(int i = min; i <= max; i++) {
        values.add(new SelectItem(i, String.valueOf(i)));
    }
    return values;
}

private int getPresentYear() {
    Calendar cal = Calendar.getInstance();
    cal.setTime(new Date());

    return cal.get(Calendar.YEAR);
}

public void minYearChanged(ValueChangeEvent event) {
    int newValue = new Integer(event.getNewValue().toString());
    this.maxYearValues = fillYearValues(newValue, maxYear);
}

public void maxYearChanged(ValueChangeEvent event) {
    int newValue = new Integer(event.getNewValue().toString());
    this.minYearValues = fillYearValues(minYear, newValue);
}

Solution

  • Finally I found a solution. Here's how I did it:

    <a4j:region renderRegionOnly="true">
    
            <%-- Year filter --%>
            <h:selectOneMenu id="minYear" value="#{statistics.minYear}" 
                             style="width: 75px" onchange="this.form.submit()"
                             valueChangeListener="#{statistics.minYearChanged}">
                <f:selectItems value="#{statistics.minYearValues}" />
            </h:selectOneMenu>
    
            <f:verbatim>&#160;&#160;</f:verbatim>
            <h:outputText value="#{bundleStatistics['Label.minYearToMaxYear']}" />
            <f:verbatim>&#160;&#160;</f:verbatim>
    
            <h:selectOneMenu id="maxYear" value="#{statistics.maxYear}" 
                             style="width: 75px" onchange="this.form.submit()"
                             valueChangeListener="#{statistics.maxYearChanged}">
                <f:selectItems  value="#{statistics.maxYearValues}"/>
            </h:selectOneMenu>
        <%-- end year filter--%>
    
    </a4j:region>
    

    Value change listeners:

    public void minYearChanged(ValueChangeEvent event) {
        int newValue = new Integer(event.getNewValue().toString());
        this.maxYearValues = fillYearValues(newValue, getPresentYear());
    }
    
    public void maxYearChanged(ValueChangeEvent event) {
        int newValue = new Integer(event.getNewValue().toString());
        this.minYearValues = fillYearValues(MIN_YEAR, newValue);
    }